grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add testpci command (v3)


From: Jonathan McDowell
Subject: Re: [PATCH] Add testpci command (v3)
Date: Fri, 12 Oct 2012 15:18:05 -0700
User-agent: Mutt/1.5.20 (2009-06-14)

On Wed, Oct 10, 2012 at 05:21:45PM -0700, Jonathan McDowell wrote:
> On Thu, Sep 27, 2012 at 02:42:11PM -0700, Jonathan McDowell wrote:
> > I have a machine with both Linux and Windows installed on the hard
> > drive. Linux runs on the bare metal and I occasionally run the Windows
> > install in a VM using KVM pointed at /dev/sda. However if I'm not quick
> > enough, or Windows decides to reboot when I'm not around to notice, the
> > grub running under KVM will decide to boot Linux and much confusion
> > ensues.
> > 
> > I couldn't find an easy way to test what the running environment was, so
> > I knocked up a simple testpci command that allows me to test for the
> > existence of a PCI device and change the default boot option based on
> > that. I have:
> > 
> > | if testpci 8086:1237; then
> > |   set default="2"
> > | fi
> > 
> > in my grub.cfg to correctly select the Windows partition if the qemu
> > provided host bridge is present.
> 
> So, a v2, changing to use --vendor/--product and also adding
> --subvendor/--subproduct as it was pointed out to me that the subsystem
> information can be used to confirm the hypervisor presence. I now have:
> 
> | if testpci --vendor=0x8086 --subvendor=0x1af4 --subproduct=0x1100; then
> |   set default="2"
> | fi
> 
> which looks for an Intel device that has a Red Hat / KVM subsystem ID.

And here's v3, which adds some minimal documentation about the new
command.

Signed-off-by: Jonathan McDowell <address@hidden>

-----
=== modified file 'docs/grub.texi'
--- docs/grub.texi      2012-07-31 22:18:57 +0000
+++ docs/grub.texi      2012-10-12 22:13:23 +0000
@@ -3302,6 +3302,7 @@
 * search::                      Search devices by file, label, or UUID
 * sendkey::                     Emulate keystrokes
 * set::                         Set an environment variable
+* testpci::                     Test for the existence of a PCI device
 * true::                        Do nothing, successfully
 * unset::                       Unset an environment variable
 * uppermem::                    Set the upper memory size
@@ -4068,6 +4069,18 @@
 @end deffn
 
 
address@hidden testpci
address@hidden testpci
+
address@hidden Command testpci address@hidden @
+  address@hidden address@hidden VENDORID}] @
+  address@hidden PRODUCTID}]
+Test for the existence of a given PCI device. Returns true if a device
+matching the specified vendor/product and/or subvendor/subproduct information
+is found.
address@hidden deffn
+
+
 @node true
 @subsection true
 

=== modified file 'grub-core/Makefile.core.def'
--- grub-core/Makefile.core.def 2012-09-08 07:40:24 +0000
+++ grub-core/Makefile.core.def 2012-09-27 21:00:31 +0000
@@ -837,6 +837,12 @@
 };
 
 module = {
+  name = testpci;
+  common = commands/testpci.c;
+  enable = pci;
+};
+
+module = {
   name = true;
   common = commands/true.c;
 };

=== added file 'grub-core/commands/testpci.c'
--- grub-core/commands/testpci.c        1970-01-01 00:00:00 +0000
+++ grub-core/commands/testpci.c        2012-10-12 22:08:21 +0000
@@ -0,0 +1,114 @@
+/* testpci.c - Test for PCI device existence.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2012  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/pci.h>
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options[] =
+  {
+    {"vendor", 'v' , 0, N_("PCI vendor ID to look for"), 0, ARG_TYPE_INT},
+    {"product", 'p' , 0, N_("PCI product ID to look for"), 0, ARG_TYPE_INT},
+    {"subvendor", 's' , 0, N_("PCI subsystem vendor ID to look for"), 0, 
ARG_TYPE_INT},
+    {"subproduct", 't' , 0, N_("PCI subsystem product ID to look for"), 0, 
ARG_TYPE_INT},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static int pcifound;
+static grub_uint32_t pcimask, pcisubmask;
+static grub_pci_id_t pcisearch;
+static grub_pci_id_t pcisubsearch;
+
+static int NESTED_FUNC_ATTR
+grub_testpci_iter (grub_pci_device_t dev __attribute__ ((unused)),
+                   grub_pci_id_t pciid)
+{
+  grub_pci_address_t addr;
+  grub_uint32_t subsystem;
+
+  if ((pciid & pcimask) != pcisearch) {
+    return 0;
+  }
+
+  if (pcisubmask != 0) {
+    addr = grub_pci_make_address (dev, GRUB_PCI_REG_SUBVENDOR);
+    subsystem = grub_pci_read (addr);
+    if ((subsystem & pcisubmask) != pcisubsearch) {
+      return 0;
+    }
+  }
+
+  pcifound = 1;
+  return 1;
+}
+
+static grub_err_t
+grub_cmd_testpci (grub_extcmd_context_t ctxt,
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  struct grub_arg_list *state = ctxt->state;
+
+  pcifound = pcimask = pcisubmask = pcisearch = pcisubsearch = 0;
+
+  if (state[0].set) {
+    pcisearch |= grub_strtoull (state[0].arg, 0, 16);
+    pcimask |= 0xFFFF;
+  }
+
+  if (state[1].set) {
+    pcisearch |= (grub_strtoull (state[1].arg, 0, 16) << 16);
+    pcimask |= 0xFFFF0000;
+  }
+
+  if (state[2].set) {
+    pcisubsearch |= grub_strtoull (state[2].arg, 0, 16);
+    pcisubmask |= 0xFFFF;
+  }
+
+  if (state[3].set) {
+    pcisubsearch |= (grub_strtoull (state[3].arg, 0, 16) << 16);
+    pcisubmask |= 0xFFFF0000;
+  }
+
+  grub_pci_iterate (grub_testpci_iter);
+
+  return pcifound ? GRUB_ERR_NONE : grub_error (GRUB_ERR_TEST_FAILURE, 
"false");
+}
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(testpci)
+{
+  cmd = grub_register_extcmd ("testpci", grub_cmd_testpci, 0,
+                              N_("[--vendor=VENDORID] [--product=PRODUCTID] "
+                                 "[--subvendor=VENDORID] "
+                                 "[--subproduct=PRODUCTID]"),
+                              N_("Test for PCI device existence."),
+                              options);
+}
+
+GRUB_MOD_FINI(testpci)
+{
+  grub_unregister_extcmd (cmd);
+}

-----

J.

-- 
You drive a hard bargain for a seagull.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]