~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to commands/setpci.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* lspci.c - List PCI devices.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2008, 2009  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/pci.h>
21
 
#include <grub/dl.h>
22
 
#include <grub/misc.h>
23
 
#include <grub/extcmd.h>
24
 
#include <grub/env.h>
25
 
#include <grub/mm.h>
26
 
 
27
 
struct pci_register
28
 
{
29
 
  const char *name;
30
 
  grub_uint16_t addr;
31
 
  unsigned size;
32
 
};
33
 
 
34
 
struct pci_register pci_registers[] =
35
 
  {
36
 
    {"VENDOR_ID",       GRUB_PCI_REG_VENDOR      , 2},
37
 
    {"DEVICE_ID",       GRUB_PCI_REG_DEVICE      , 2},
38
 
    {"COMMAND",         GRUB_PCI_REG_COMMAND     , 2},
39
 
    {"STATUS",          GRUB_PCI_REG_STATUS      , 2},
40
 
    {"REVISION",        GRUB_PCI_REG_REVISION    , 1},
41
 
    {"CLASS_PROG",      GRUB_PCI_REG_CLASS + 1   , 1},
42
 
    {"CLASS_DEVICE",    GRUB_PCI_REG_CLASS + 2   , 2},
43
 
    {"CACHE_LINE_SIZE", GRUB_PCI_REG_CACHELINE   , 1},
44
 
    {"LATENCY_TIMER",   GRUB_PCI_REG_LAT_TIMER   , 1},
45
 
    {"HEADER_TYPE",     GRUB_PCI_REG_HEADER_TYPE , 1},
46
 
    {"BIST",            GRUB_PCI_REG_BIST        , 1},
47
 
    {"BASE_ADDRESS_0",  GRUB_PCI_REG_ADDRESS_REG0, 4},
48
 
    {"BASE_ADDRESS_1",  GRUB_PCI_REG_ADDRESS_REG1, 4},
49
 
    {"BASE_ADDRESS_2",  GRUB_PCI_REG_ADDRESS_REG2, 4},
50
 
    {"BASE_ADDRESS_3",  GRUB_PCI_REG_ADDRESS_REG3, 4},
51
 
    {"BASE_ADDRESS_4",  GRUB_PCI_REG_ADDRESS_REG4, 4},
52
 
    {"BASE_ADDRESS_5",  GRUB_PCI_REG_ADDRESS_REG5, 4},
53
 
    {"CARDBUS_CIS",     GRUB_PCI_REG_CIS_POINTER , 4},
54
 
    {"SUBVENDOR_ID",    GRUB_PCI_REG_SUBVENDOR   , 2},
55
 
    {"SUBSYSTEM_ID",    GRUB_PCI_REG_SUBSYSTEM   , 2},
56
 
    {"ROM_ADDRESS",     GRUB_PCI_REG_ROM_ADDRESS , 4},
57
 
    {"CAP_POINTER",     GRUB_PCI_REG_CAP_POINTER , 1},
58
 
    {"INTERRUPT_LINE",  GRUB_PCI_REG_IRQ_LINE    , 1},
59
 
    {"INTERRUPT_PIN",   GRUB_PCI_REG_IRQ_PIN     , 1},
60
 
    {"MIN_GNT",         GRUB_PCI_REG_MIN_GNT     , 1},
61
 
    {"MAX_LAT",         GRUB_PCI_REG_MIN_GNT     , 1},
62
 
  };
63
 
 
64
 
static const struct grub_arg_option options[] =
65
 
  {
66
 
    {0, 'd', 0, "Select device by vendor and device IDs.",
67
 
     "[vendor]:[device]", ARG_TYPE_STRING},
68
 
    {0, 's', 0, "Select device by its position on the bus.",
69
 
     "[bus]:[slot][.func]", ARG_TYPE_STRING},
70
 
    {0, 'v', 0, "Save read value into variable VARNAME.",
71
 
     "VARNAME", ARG_TYPE_STRING},
72
 
    {0, 0, 0, 0, 0, 0}
73
 
  };
74
 
 
75
 
static grub_uint32_t pciid_check_mask, pciid_check_value;
76
 
static int bus, device, function;
77
 
static int check_bus, check_device, check_function;
78
 
static grub_uint32_t write_mask, regwrite;
79
 
static int regsize;
80
 
static grub_uint16_t regaddr;
81
 
static const char *varname;
82
 
 
83
 
static int NESTED_FUNC_ATTR
84
 
grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
85
 
{
86
 
  grub_uint32_t regval = 0;
87
 
  grub_pci_address_t addr;
88
 
 
89
 
  if ((pciid & pciid_check_mask) != pciid_check_value)
90
 
    return 0;
91
 
 
92
 
  if (check_bus && grub_pci_get_bus (dev) != bus)
93
 
    return 0;
94
 
 
95
 
  if (check_device && grub_pci_get_device (dev) != device)
96
 
    return 0;
97
 
 
98
 
  if (check_function && grub_pci_get_function (dev) != device)
99
 
    return 0;
100
 
 
101
 
  addr = grub_pci_make_address (dev, regaddr);
102
 
 
103
 
  switch (regsize)
104
 
    {
105
 
    case 1:
106
 
      regval = grub_pci_read_byte (addr);
107
 
      break;
108
 
 
109
 
    case 2:
110
 
      regval = grub_pci_read_word (addr);
111
 
      break;
112
 
 
113
 
    case 4:
114
 
      regval = grub_pci_read (addr);
115
 
      break;
116
 
    }
117
 
 
118
 
  if (varname)
119
 
    {
120
 
      char buf[sizeof ("XXXXXXXX")];
121
 
      grub_snprintf (buf, sizeof (buf), "%x", regval);
122
 
      grub_env_set (varname, buf);
123
 
      return 1;
124
 
    }
125
 
 
126
 
  if (!write_mask)
127
 
    {
128
 
      grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr,
129
 
                   grub_pci_get_bus (dev),
130
 
                   grub_pci_get_device (dev),
131
 
                   grub_pci_get_function (dev),
132
 
                   regval);
133
 
      return 0;
134
 
    }
135
 
 
136
 
  regval = (regval & ~write_mask) | regwrite;
137
 
 
138
 
  switch (regsize)
139
 
    {
140
 
    case 1:
141
 
      grub_pci_write_byte (addr, regval);
142
 
      break;
143
 
 
144
 
    case 2:
145
 
      grub_pci_write_word (addr, regval);
146
 
      break;
147
 
 
148
 
    case 4:
149
 
      grub_pci_write (addr, regval);
150
 
      break;
151
 
    }
152
 
 
153
 
  return 0;
154
 
}
155
 
 
156
 
static grub_err_t
157
 
grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
158
 
{
159
 
  const char *ptr;
160
 
  unsigned i;
161
 
 
162
 
  pciid_check_value = 0;
163
 
  pciid_check_mask = 0;
164
 
 
165
 
  if (cmd->state[0].set)
166
 
    {
167
 
      ptr = cmd->state[0].arg;
168
 
      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
169
 
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
170
 
        {
171
 
          grub_errno = GRUB_ERR_NONE;
172
 
          ptr = cmd->state[0].arg;
173
 
        }
174
 
      else
175
 
        pciid_check_mask |= 0xffff;
176
 
      if (grub_errno)
177
 
        return grub_errno;
178
 
      if (*ptr != ':')
179
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
180
 
      ptr++;
181
 
      pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
182
 
        << 16;
183
 
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
184
 
        grub_errno = GRUB_ERR_NONE;
185
 
      else
186
 
        pciid_check_mask |= 0xffff0000;
187
 
    }
188
 
 
189
 
  pciid_check_value &= pciid_check_mask;
190
 
 
191
 
  check_bus = check_device = check_function = 0;
192
 
 
193
 
  if (cmd->state[1].set)
194
 
    {
195
 
      const char *optr;
196
 
      
197
 
      ptr = cmd->state[1].arg;
198
 
      optr = ptr;
199
 
      bus = grub_strtoul (ptr, (char **) &ptr, 16);
200
 
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
201
 
        {
202
 
          grub_errno = GRUB_ERR_NONE;
203
 
          ptr = optr;
204
 
        }
205
 
      else
206
 
        check_bus = 1;
207
 
      if (grub_errno)
208
 
        return grub_errno;
209
 
      if (*ptr != ':')
210
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
211
 
      ptr++;
212
 
      optr = ptr;
213
 
      device = grub_strtoul (ptr, (char **) &ptr, 16);
214
 
      if (grub_errno == GRUB_ERR_BAD_NUMBER)
215
 
        {
216
 
          grub_errno = GRUB_ERR_NONE;
217
 
          ptr = optr;
218
 
        }
219
 
      else
220
 
        check_device = 1;
221
 
      if (*ptr == '.')
222
 
        {
223
 
          ptr++;
224
 
          function = grub_strtoul (ptr, (char **) &ptr, 16);
225
 
          if (grub_errno)
226
 
            return grub_errno;
227
 
          check_function = 1;
228
 
        }
229
 
    }
230
 
 
231
 
  if (cmd->state[2].set)
232
 
    varname = cmd->state[2].arg;
233
 
  else
234
 
    varname = NULL;
235
 
 
236
 
  write_mask = 0;
237
 
 
238
 
  if (argc == 0)
239
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected.");
240
 
 
241
 
  if (argc > 1)
242
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported.");
243
 
 
244
 
  ptr = argv[0];
245
 
 
246
 
  for (i = 0; i < ARRAY_SIZE (pci_registers); i++)
247
 
    {
248
 
      if (grub_strncmp (ptr, pci_registers[i].name,
249
 
                        grub_strlen (pci_registers[i].name)) == 0)
250
 
        break;
251
 
    }
252
 
  if (i == ARRAY_SIZE (pci_registers))
253
 
    {
254
 
      regsize = 0;
255
 
      regaddr = grub_strtoul (ptr, (char **) &ptr, 16);
256
 
      if (grub_errno)
257
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register");
258
 
    }
259
 
  else
260
 
    {
261
 
      regaddr = pci_registers[i].addr;
262
 
      regsize = pci_registers[i].size;
263
 
      ptr += grub_strlen (pci_registers[i].name);
264
 
    }
265
 
 
266
 
  if (grub_errno)
267
 
    return grub_errno;
268
 
 
269
 
  if (*ptr == '+')
270
 
    {
271
 
      ptr++;
272
 
      regaddr += grub_strtoul (ptr, (char **) &ptr, 16);
273
 
      if (grub_errno)
274
 
        return grub_errno;
275
 
    }
276
 
 
277
 
  if (grub_memcmp (ptr, ".L", sizeof (".L") - 1) == 0
278
 
      || grub_memcmp (ptr, ".l", sizeof (".l") - 1) == 0)
279
 
    {
280
 
      regsize = 4;
281
 
      ptr += sizeof (".l") - 1;
282
 
    }
283
 
  else if (grub_memcmp (ptr, ".W", sizeof (".W") - 1) == 0
284
 
      || grub_memcmp (ptr, ".w", sizeof (".w") - 1) == 0)
285
 
    {
286
 
      regsize = 2;
287
 
      ptr += sizeof (".w") - 1;
288
 
    }
289
 
  else if (grub_memcmp (ptr, ".B", sizeof (".B") - 1) == 0
290
 
      || grub_memcmp (ptr, ".b", sizeof (".b") - 1) == 0)
291
 
    {
292
 
      regsize = 1;
293
 
      ptr += sizeof (".b") - 1;
294
 
    }
295
 
 
296
 
  if (!regsize)
297
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
298
 
                       "Unknown register size.");
299
 
 
300
 
  write_mask = 0;
301
 
  if (*ptr == '=')
302
 
    {
303
 
      ptr++;
304
 
      regwrite = grub_strtoul (ptr, (char **) &ptr, 16);
305
 
      if (grub_errno)
306
 
        return grub_errno;
307
 
      write_mask = 0xffffffff;
308
 
      if (*ptr == ':')
309
 
        {
310
 
          ptr++;
311
 
          write_mask = grub_strtoul (ptr, (char **) &ptr, 16);
312
 
          if (grub_errno)
313
 
            return grub_errno;
314
 
          write_mask = 0xffffffff;
315
 
        }
316
 
      regwrite &= write_mask;
317
 
    }
318
 
 
319
 
  if (write_mask && varname)
320
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
321
 
                       "Option -v isn't valid for writes.");
322
 
 
323
 
  grub_pci_iterate (grub_setpci_iter);
324
 
  return GRUB_ERR_NONE;
325
 
}
326
 
 
327
 
static grub_extcmd_t cmd;
328
 
 
329
 
GRUB_MOD_INIT(setpci)
330
 
{
331
 
  cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH,
332
 
                              "setpci [-s POSITION] [-d DEVICE] [-v VAR] "
333
 
                              "[REGISTER][=VALUE[:MASK]]",
334
 
                              "Manipulate PCI devices.", options);
335
 
}
336
 
 
337
 
GRUB_MOD_FINI(setpci)
338
 
{
339
 
  grub_unregister_extcmd (cmd);
340
 
}