From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1TM6X9-0001Fg-Ri for mharc-grub-devel@gnu.org; Wed, 10 Oct 2012 20:21:51 -0400 Received: from eggs.gnu.org ([208.118.235.92]:33263) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TM6X7-0001F9-Ey for grub-devel@gnu.org; Wed, 10 Oct 2012 20:21:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TM6X5-0004pQ-Ui for grub-devel@gnu.org; Wed, 10 Oct 2012 20:21:49 -0400 Received: from the.earth.li ([46.43.34.31]:45174) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TM6X5-0004p5-LE for grub-devel@gnu.org; Wed, 10 Oct 2012 20:21:47 -0400 Received: from noodles by the.earth.li with local (Exim 4.72) (envelope-from ) id 1TM6X3-0003ba-Fu for grub-devel@gnu.org; Thu, 11 Oct 2012 01:21:45 +0100 Date: Wed, 10 Oct 2012 17:21:45 -0700 From: Jonathan McDowell To: grub-devel@gnu.org Subject: Re: [PATCH] Add testpci command (v2) Message-ID: <20121011002145.GV2289@earth.li> References: <20120927214211.GS2289@earth.li> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20120927214211.GS2289@earth.li> User-Agent: Mutt/1.5.20 (2009-06-14) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 46.43.34.31 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Oct 2012 00:21:51 -0000 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. Signed-off-by: Jonathan McDowell ----- === 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-11 00:13:12 +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 . + */ + +#include +#include +#include +#include +#include + +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. -- Web [ "Don't pull the trigger. That would kinda give away the ] site: http:// [ game." ] Made by www.earth.li/~noodles/ [ ] HuggieTag 0.0.24