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

« back to all changes in this revision

Viewing changes to grub-core/commands/hdparm.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* hdparm.c - command to get/set ATA disk parameters.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 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/ata.h>
 
21
#include <grub/disk.h>
 
22
#include <grub/dl.h>
 
23
#include <grub/misc.h>
 
24
#include <grub/mm.h>
 
25
#include <grub/lib/hexdump.h>
 
26
#include <grub/extcmd.h>
 
27
#include <grub/i18n.h>
 
28
 
 
29
static const struct grub_arg_option options[] = {
 
30
  {"apm",             'B', 0, N_("Set Advanced Power Management\n"
 
31
                              "(1=low, ..., 254=high, 255=off)."),
 
32
                              0, ARG_TYPE_INT},
 
33
  {"power",           'C', 0, N_("Check power mode."), 0, ARG_TYPE_NONE},
 
34
  {"security-freeze", 'F', 0, N_("Freeze ATA security settings until reset."),
 
35
                              0, ARG_TYPE_NONE},
 
36
  {"health",          'H', 0, N_("Check SMART health status."), 0, ARG_TYPE_NONE},
 
37
  {"aam",             'M', 0, N_("Set Automatic Acoustic Management\n"
 
38
                              "(0=off, 128=quiet, ..., 254=fast)."),
 
39
                              0, ARG_TYPE_INT},
 
40
  {"standby-timeout", 'S', 0, N_("Set standby timeout\n"
 
41
                              "(0=off, 1=5s, 2=10s, ..., 240=20m, 241=30m, ...)."),
 
42
                              0, ARG_TYPE_INT},
 
43
  {"standby",         'y', 0, N_("Set drive to standby mode."), 0, ARG_TYPE_NONE},
 
44
  {"sleep",           'Y', 0, N_("Set drive to sleep mode."), 0, ARG_TYPE_NONE},
 
45
  {"identify",        'i', 0, N_("Print drive identity and settings."),
 
46
                              0, ARG_TYPE_NONE},
 
47
  {"dumpid",          'I', 0, N_("Dump contents of ATA IDENTIFY sector."),
 
48
                               0, ARG_TYPE_NONE},
 
49
  {"smart",            -1, 0, N_("Disable/enable SMART (0/1)."), 0, ARG_TYPE_INT},
 
50
  {"quiet",           'q', 0, N_("Do not print messages."), 0, ARG_TYPE_NONE},
 
51
  {0, 0, 0, 0, 0, 0}
 
52
};
 
53
 
 
54
enum grub_ata_smart_commands
 
55
  {
 
56
    GRUB_ATA_FEAT_SMART_ENABLE  = 0xd8,
 
57
    GRUB_ATA_FEAT_SMART_DISABLE = 0xd9,
 
58
    GRUB_ATA_FEAT_SMART_STATUS  = 0xda,
 
59
  };
 
60
 
 
61
static int quiet = 0;
 
62
 
 
63
static grub_err_t
 
64
grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
 
65
                        grub_uint8_t features, grub_uint8_t sectors,
 
66
                        void * buffer, int size)
 
67
{
 
68
  struct grub_disk_ata_pass_through_parms apt;
 
69
  grub_memset (&apt, 0, sizeof (apt));
 
70
 
 
71
  apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
 
72
  apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
 
73
  apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
 
74
  apt.buffer = buffer;
 
75
  apt.size = size;
 
76
 
 
77
  if (grub_disk_ata_pass_through (disk, &apt))
 
78
    return grub_errno;
 
79
 
 
80
  return GRUB_ERR_NONE;
 
81
}
 
82
 
 
83
static int
 
84
grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
 
85
{
 
86
  struct grub_disk_ata_pass_through_parms apt;
 
87
  grub_memset (&apt, 0, sizeof (apt));
 
88
 
 
89
  apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
 
90
 
 
91
  if (grub_disk_ata_pass_through (disk, &apt))
 
92
    return -1;
 
93
 
 
94
  return apt.taskfile[GRUB_ATA_REG_SECTORS];
 
95
}
 
96
 
 
97
static int
 
98
grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
 
99
{
 
100
  struct grub_disk_ata_pass_through_parms apt;
 
101
  grub_memset (&apt, 0, sizeof (apt));
 
102
 
 
103
  apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
 
104
  apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
 
105
  apt.taskfile[GRUB_ATA_REG_LBAMID]  = 0x4f;
 
106
  apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
 
107
 
 
108
  if (grub_disk_ata_pass_through (disk, &apt))
 
109
    return -1;
 
110
 
 
111
  if (features == GRUB_ATA_FEAT_SMART_STATUS)
 
112
    {
 
113
      if (   apt.taskfile[GRUB_ATA_REG_LBAMID]  == 0x4f
 
114
          && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
 
115
        return 0; /* Good SMART status.  */
 
116
      else if (   apt.taskfile[GRUB_ATA_REG_LBAMID]  == 0xf4
 
117
               && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
 
118
        return 1; /* Bad SMART status.  */
 
119
      else
 
120
        return -1;
 
121
    }
 
122
  return 0;
 
123
}
 
124
 
 
125
static grub_err_t
 
126
grub_hdparm_simple_cmd (const char * msg,
 
127
                        grub_disk_t disk, grub_uint8_t cmd)
 
128
{
 
129
  if (! quiet && msg)
 
130
    grub_printf ("%s", msg);
 
131
 
 
132
  grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
 
133
 
 
134
  if (! quiet && msg)
 
135
    grub_printf ("%s\n", ! err ? "" : ": not supported");
 
136
  return err;
 
137
}
 
138
 
 
139
static grub_err_t
 
140
grub_hdparm_set_val_cmd (const char * msg, int val,
 
141
                         grub_disk_t disk, grub_uint8_t cmd,
 
142
                         grub_uint8_t features, grub_uint8_t sectors)
 
143
{
 
144
  if (! quiet && msg && *msg)
 
145
    {
 
146
      if (val >= 0)
 
147
        grub_printf ("Set %s to %d", msg, val);
 
148
      else
 
149
        grub_printf ("Disable %s", msg);
 
150
    }
 
151
 
 
152
  grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
 
153
                                           NULL, 0);
 
154
 
 
155
  if (! quiet && msg)
 
156
    grub_printf ("%s\n", ! err ? "" : ": not supported");
 
157
  return err;
 
158
}
 
159
 
 
160
static const char *
 
161
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
 
162
{
 
163
  grub_uint16_t * dest16 = (grub_uint16_t *) dest;
 
164
  unsigned i;
 
165
  for (i = 0; i < bytes / 2; i++)
 
166
    dest16[i] = grub_be_to_cpu16 (src16[i]);
 
167
  return dest;
 
168
}
 
169
 
 
170
static void
 
171
grub_hdparm_print_identify (const char * idbuf)
 
172
{
 
173
  const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
 
174
 
 
175
  /* Print identity strings.  */
 
176
  char tmp[40];
 
177
  grub_printf ("Model:    \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
 
178
  grub_printf ("Firmware: \"%.8s\"\n",  le16_to_char (tmp, &idw[23], 8));
 
179
  grub_printf ("Serial:   \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
 
180
 
 
181
  /* Print AAM, APM and SMART settings.  */
 
182
  grub_uint16_t features1 = grub_le_to_cpu16 (idw[82]);
 
183
  grub_uint16_t features2 = grub_le_to_cpu16 (idw[83]);
 
184
  grub_uint16_t enabled1  = grub_le_to_cpu16 (idw[85]);
 
185
  grub_uint16_t enabled2  = grub_le_to_cpu16 (idw[86]);
 
186
 
 
187
  grub_printf ("Automatic Acoustic Management: ");
 
188
  if (features2 & 0x0200)
 
189
    {
 
190
      if (enabled2 & 0x0200)
 
191
        {
 
192
          grub_uint16_t aam = grub_le_to_cpu16 (idw[94]);
 
193
          grub_printf ("%u (128=quiet, ..., 254=fast, recommended=%u)\n",
 
194
                       aam & 0xff, (aam >> 8) & 0xff);
 
195
        }
 
196
      else
 
197
        grub_printf ("disabled\n");
 
198
    }
 
199
  else
 
200
    grub_printf ("not supported\n");
 
201
 
 
202
  grub_printf ("Advanced Power Management: ");
 
203
  if (features2 & 0x0008)
 
204
    {
 
205
      if (enabled2 & 0x0008)
 
206
        grub_printf ("%u (1=low, ..., 254=high)\n",
 
207
                     grub_le_to_cpu16 (idw[91]) & 0xff);
 
208
      else
 
209
        grub_printf ("disabled\n");
 
210
    }
 
211
  else
 
212
    grub_printf ("not supported\n");
 
213
 
 
214
  grub_printf ("SMART Feature Set: ");
 
215
  if (features1 & 0x0001)
 
216
    grub_printf ("%sabled\n", (enabled1 & 0x0001 ? "en" : "dis"));
 
217
  else
 
218
    grub_printf ("not supported\n");
 
219
 
 
220
  /* Print security settings.  */
 
221
  grub_uint16_t security = grub_le_to_cpu16 (idw[128]);
 
222
 
 
223
  grub_printf ("ATA Security: ");
 
224
  if (security & 0x0001)
 
225
    grub_printf ("%s, %s, %s, %s\n",
 
226
                 (security & 0x0002 ? "ENABLED" : "disabled"),
 
227
                 (security & 0x0004 ? "**LOCKED**"  : "not locked"),
 
228
                 (security & 0x0008 ? "frozen" : "NOT FROZEN"),
 
229
                 (security & 0x0010 ? "COUNT EXPIRED" : "count not expired"));
 
230
  else
 
231
    grub_printf ("not supported\n");
 
232
}
 
233
 
 
234
static void
 
235
grub_hdparm_print_standby_tout (int timeout)
 
236
{
 
237
  if (timeout == 0)
 
238
    grub_printf ("off");
 
239
  else if (timeout <= 252 || timeout == 255)
 
240
    {
 
241
      int h = 0, m = 0 , s = 0;
 
242
      if (timeout == 255)
 
243
        {
 
244
          m = 21;
 
245
          s = 15;
 
246
        }
 
247
      else if (timeout == 252)
 
248
        m = 21;
 
249
      else if (timeout <= 240)
 
250
        {
 
251
          s = timeout * 5;
 
252
          m = s / 60;
 
253
          s %= 60;
 
254
        }
 
255
      else
 
256
        {
 
257
          m = (timeout - 240) * 30;
 
258
          h  = m / 60;
 
259
          m %= 60;
 
260
        }
 
261
      grub_printf ("%02d:%02d:%02d", h, m, s);
 
262
    }
 
263
  else
 
264
    grub_printf ("invalid or vendor-specific");
 
265
}
 
266
 
 
267
static int get_int_arg (const struct grub_arg_list *state)
 
268
{
 
269
  return (state->set ? (int)grub_strtoul (state->arg, 0, 0) : -1);
 
270
}
 
271
 
 
272
static grub_err_t
 
273
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
 
274
{
 
275
  struct grub_arg_list *state = ctxt->state;
 
276
 
 
277
  /* Check command line.  */
 
278
  if (argc != 1)
 
279
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument");
 
280
 
 
281
  grub_size_t len = grub_strlen (args[0]);
 
282
  if (! (args[0][0] == '(' && args[0][len - 1] == ')'))
 
283
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
 
284
  args[0][len - 1] = 0;
 
285
 
 
286
  if (! grub_disk_ata_pass_through)
 
287
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
 
288
 
 
289
  int i = 0;
 
290
  int apm          = get_int_arg (&state[i++]);
 
291
  int power        = state[i++].set;
 
292
  int sec_freeze   = state[i++].set;
 
293
  int health       = state[i++].set;
 
294
  int aam          = get_int_arg (&state[i++]);
 
295
  int standby_tout = get_int_arg (&state[i++]);
 
296
  int standby_now  = state[i++].set;
 
297
  int sleep_now    = state[i++].set;
 
298
  int ident        = state[i++].set;
 
299
  int dumpid       = state[i++].set;
 
300
  int enable_smart = get_int_arg (&state[i++]);
 
301
  quiet            = state[i++].set;
 
302
 
 
303
  /* Open disk.  */
 
304
  grub_disk_t disk = grub_disk_open (&args[0][1]);
 
305
  if (! disk)
 
306
    return grub_errno;
 
307
 
 
308
  if (disk->partition)
 
309
    {
 
310
      grub_disk_close (disk);
 
311
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
 
312
    }
 
313
 
 
314
  /* Change settings.  */
 
315
  if (aam >= 0)
 
316
    grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
 
317
      disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
 
318
 
 
319
  if (apm >= 0)
 
320
    grub_hdparm_set_val_cmd ("Advanced Power Management",
 
321
      (apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
 
322
      (apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
 
323
 
 
324
  if (standby_tout >= 0)
 
325
    {
 
326
      if (! quiet)
 
327
        {
 
328
          grub_printf ("Set standby timeout to %d (", standby_tout);
 
329
          grub_hdparm_print_standby_tout (standby_tout);
 
330
          grub_printf (")");
 
331
        }
 
332
      /* The IDLE cmd sets disk to idle mode and configures standby timer.  */
 
333
      grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
 
334
    }
 
335
 
 
336
  if (enable_smart >= 0)
 
337
    {
 
338
      if (! quiet)
 
339
        grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
 
340
      int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
 
341
                  GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
 
342
      if (! quiet)
 
343
        grub_printf ("%s\n", err ? ": not supported" : "");
 
344
    }
 
345
 
 
346
  if (sec_freeze)
 
347
    grub_hdparm_simple_cmd ("Freeze security settings", disk,
 
348
                            GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
 
349
 
 
350
  /* Print/dump IDENTIFY.  */
 
351
  if (ident || dumpid)
 
352
    {
 
353
      char buf[GRUB_DISK_SECTOR_SIZE];
 
354
      if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
 
355
          0, 0, buf, sizeof (buf)))
 
356
        grub_printf ("Cannot read ATA IDENTIFY data\n");
 
357
      else
 
358
        {
 
359
          if (ident)
 
360
            grub_hdparm_print_identify (buf);
 
361
          if (dumpid)
 
362
            hexdump (0, buf, sizeof (buf));
 
363
        }
 
364
    }
 
365
 
 
366
  /* Check power mode.  */
 
367
  if (power)
 
368
    {
 
369
      grub_printf ("Disk power mode is: ");
 
370
      int mode = grub_hdparm_do_check_powermode_cmd (disk);
 
371
      if (mode < 0)
 
372
        grub_printf ("unknown\n");
 
373
      else
 
374
        grub_printf ("%s (0x%02x)\n",
 
375
                     (mode == 0xff ? "active/idle" :
 
376
                      mode == 0x80 ? "idle" :
 
377
                      mode == 0x00 ? "standby" : "unknown"), mode);
 
378
    }
 
379
 
 
380
  /* Check health.  */
 
381
  int status = 0;
 
382
  if (health)
 
383
    {
 
384
      if (! quiet)
 
385
        grub_printf ("SMART status is: ");
 
386
      int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
 
387
      if (! quiet)
 
388
        grub_printf ("%s\n", (err  < 0 ? "unknown" :
 
389
                              err == 0 ? "OK" : "*BAD*"));
 
390
      status = (err > 0);
 
391
    }
 
392
 
 
393
  /* Change power mode.  */
 
394
  if (standby_now)
 
395
    grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
 
396
                            GRUB_ATA_CMD_STANDBY_IMMEDIATE);
 
397
 
 
398
  if (sleep_now)
 
399
    grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
 
400
                            GRUB_ATA_CMD_SLEEP);
 
401
 
 
402
  grub_disk_close (disk);
 
403
 
 
404
  grub_errno = GRUB_ERR_NONE;
 
405
  return status;
 
406
}
 
407
 
 
408
static grub_extcmd_t cmd;
 
409
 
 
410
GRUB_MOD_INIT(hdparm)
 
411
{
 
412
  cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0,
 
413
                              N_("[OPTIONS] DISK"),
 
414
                              N_("Get/set ATA disk parameters."), options);
 
415
}
 
416
 
 
417
GRUB_MOD_FINI(hdparm)
 
418
{
 
419
  grub_unregister_extcmd (cmd);
 
420
}