~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/commands/acpihalt.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
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2010  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB is free software: you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation, either version 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#ifdef GRUB_DSDT_TEST
 
20
#include <stdio.h>
 
21
#include <unistd.h>
 
22
#include <stdlib.h>
 
23
#include <stdint.h>
 
24
#include <string.h>
 
25
 
 
26
#define grub_dprintf(cond, args...) printf ( args )
 
27
#define grub_printf printf
 
28
typedef uint64_t grub_uint64_t;
 
29
typedef uint32_t grub_uint32_t;
 
30
typedef uint16_t grub_uint16_t;
 
31
typedef uint8_t grub_uint8_t;
 
32
 
 
33
#endif
 
34
 
 
35
#include <grub/acpi.h>
 
36
 
 
37
#ifndef GRUB_DSDT_TEST
 
38
#include <grub/misc.h>
 
39
#include <grub/cpu/io.h>
 
40
#endif
 
41
 
 
42
static inline grub_uint32_t
 
43
decode_length (const grub_uint8_t *ptr, int *numlen)
 
44
{
 
45
  int num_bytes, i;
 
46
  grub_uint32_t ret;
 
47
  if (*ptr < 64)
 
48
    {
 
49
      if (numlen)
 
50
        *numlen = 1;
 
51
      return *ptr;
 
52
    }
 
53
  num_bytes = *ptr >> 6;
 
54
  if (numlen)
 
55
    *numlen = num_bytes + 1;
 
56
  ret = *ptr & 0xf;
 
57
  ptr++;
 
58
  for (i = 0; i < num_bytes; i++)
 
59
    {
 
60
      ret |= *ptr << (8 * i + 4);
 
61
      ptr++;
 
62
    }
 
63
  return ret;
 
64
}
 
65
 
 
66
static inline grub_uint32_t
 
67
skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end)
 
68
{
 
69
  const grub_uint8_t *ptr0 = ptr;
 
70
  
 
71
  while (ptr < end && (*ptr == '^' || *ptr == '\\'))
 
72
    ptr++;
 
73
  switch (*ptr)
 
74
    {
 
75
    case '.':
 
76
      ptr++;
 
77
      ptr += 8;
 
78
      break;
 
79
    case '/':
 
80
      ptr++;
 
81
      ptr += 1 + (*ptr) * 4;
 
82
      break;
 
83
    case 0:
 
84
      ptr++;
 
85
      break;
 
86
    default:
 
87
      ptr += 4;
 
88
      break;
 
89
    }
 
90
  return ptr - ptr0;
 
91
}
 
92
 
 
93
static inline grub_uint32_t
 
94
skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
 
95
{
 
96
  grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
 
97
  switch (*ptr)
 
98
    {
 
99
    case GRUB_ACPI_OPCODE_PACKAGE:
 
100
      return 1 + decode_length (ptr + 1, 0);
 
101
    case GRUB_ACPI_OPCODE_ZERO:
 
102
    case GRUB_ACPI_OPCODE_ONES:
 
103
    case GRUB_ACPI_OPCODE_ONE:
 
104
      return 1;
 
105
    case GRUB_ACPI_OPCODE_BYTE_CONST:
 
106
      return 2;
 
107
    case GRUB_ACPI_OPCODE_WORD_CONST:
 
108
      return 3;
 
109
    case GRUB_ACPI_OPCODE_DWORD_CONST:
 
110
      return 5;
 
111
    default:
 
112
      if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
 
113
          || (*ptr >= 'A' && *ptr <= 'Z'))
 
114
        return skip_name_string (ptr, end);
 
115
      grub_printf ("Unknown opcode 0x%x\n", *ptr);
 
116
      return 0;
 
117
    }
 
118
}
 
119
 
 
120
static inline grub_uint32_t
 
121
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
 
122
{
 
123
  const grub_uint8_t *ptr0 = ptr;
 
124
  int add;
 
125
  grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
 
126
  switch (*ptr)
 
127
    {
 
128
    case GRUB_ACPI_EXTOPCODE_MUTEX:
 
129
      ptr++;
 
130
      ptr += skip_name_string (ptr, end);
 
131
      ptr++;
 
132
      break;
 
133
    case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
 
134
      ptr++;
 
135
      ptr += skip_name_string (ptr, end);
 
136
      ptr++;
 
137
      ptr += add = skip_data_ref_object (ptr, end);
 
138
      if (!add)
 
139
        return 0;
 
140
      ptr += add = skip_data_ref_object (ptr, end);
 
141
      if (!add)
 
142
        return 0;
 
143
      break;
 
144
    case GRUB_ACPI_EXTOPCODE_FIELD_OP:
 
145
    case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP:
 
146
      ptr++;
 
147
      ptr += decode_length (ptr, 0);
 
148
      break;
 
149
    default:
 
150
      grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
 
151
      return 0;
 
152
    }
 
153
  return ptr - ptr0;
 
154
}
 
155
 
 
156
static int
 
157
get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
 
158
{
 
159
  grub_uint8_t *ptr, *prev = table;
 
160
  int sleep_type = -1;
 
161
  
 
162
  ptr = table + sizeof (struct grub_acpi_table_header);
 
163
  while (ptr < end && prev < ptr)
 
164
    {
 
165
      int add;
 
166
      prev = ptr;
 
167
      grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
 
168
      grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
 
169
      switch (*ptr)
 
170
        {
 
171
        case GRUB_ACPI_OPCODE_EXTOP:
 
172
          ptr++;
 
173
          ptr += add = skip_ext_op (ptr, end);
 
174
          if (!add)
 
175
            return -1;
 
176
          break;
 
177
        case GRUB_ACPI_OPCODE_NAME:
 
178
          ptr++;
 
179
          if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0)
 
180
            {
 
181
              int ll;
 
182
              grub_uint8_t *ptr2 = ptr;
 
183
              grub_dprintf ("acpi", "S5 found\n");
 
184
              ptr2 += skip_name_string (ptr, end);
 
185
              if (*ptr2 != 0x12)
 
186
                {
 
187
                  grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
 
188
                  return -1;
 
189
                }
 
190
              ptr2++;
 
191
              decode_length (ptr2, &ll);
 
192
              ptr2 += ll;
 
193
              ptr2++;
 
194
              switch (*ptr2)
 
195
                {
 
196
                case GRUB_ACPI_OPCODE_ZERO:
 
197
                  sleep_type = 0;
 
198
                  break;
 
199
                case GRUB_ACPI_OPCODE_ONE:
 
200
                  sleep_type = 1;
 
201
                  break;
 
202
                case GRUB_ACPI_OPCODE_BYTE_CONST:
 
203
                  sleep_type = ptr2[1];
 
204
                  break;
 
205
                default:
 
206
                  grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
 
207
                  return -1;
 
208
                }
 
209
            }
 
210
          ptr += add = skip_name_string (ptr, end);
 
211
          if (!add)
 
212
            return -1;
 
213
          ptr += add = skip_data_ref_object (ptr, end);
 
214
          if (!add)
 
215
            return -1;
 
216
          break;
 
217
        case GRUB_ACPI_OPCODE_SCOPE:
 
218
        case GRUB_ACPI_OPCODE_IF:
 
219
        case GRUB_ACPI_OPCODE_METHOD:
 
220
          {
 
221
            ptr++;
 
222
            ptr += decode_length (ptr, 0);
 
223
            break;
 
224
          }
 
225
        }
 
226
    }
 
227
 
 
228
  grub_dprintf ("acpi", "TYP = %d\n", sleep_type);
 
229
  return sleep_type;
 
230
}
 
231
 
 
232
#ifdef GRUB_DSDT_TEST
 
233
int
 
234
main (int argc, char **argv)
 
235
{
 
236
  FILE *f;
 
237
  size_t len;
 
238
  unsigned char *buf;
 
239
  if (argc < 2)
 
240
    printf ("Usage: %s FILE\n", argv[0]);
 
241
  f = fopen (argv[1], "rb");
 
242
  if (!f)
 
243
    {
 
244
      printf ("Couldn't open file\n");
 
245
      return 1;
 
246
    }
 
247
  fseek (f, 0, SEEK_END);
 
248
  len = ftell (f);
 
249
  fseek (f, 0, SEEK_SET);
 
250
  buf = malloc (len);
 
251
  if (!buf)
 
252
    {
 
253
      printf ("Couldn't malloc buffer\n");
 
254
      fclose (f);
 
255
      return 2;
 
256
    }
 
257
  if (fread (buf, 1, len, f) != len)
 
258
    {
 
259
      printf ("Read failed\n");
 
260
      free (buf);
 
261
      fclose (f);
 
262
      return 2;
 
263
    }
 
264
 
 
265
  printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len));
 
266
  free (buf);
 
267
  fclose (f);
 
268
  return 0;
 
269
}
 
270
 
 
271
#else
 
272
 
 
273
void
 
274
grub_acpi_halt (void)
 
275
{
 
276
  struct grub_acpi_rsdp_v20 *rsdp2;
 
277
  struct grub_acpi_rsdp_v10 *rsdp1;
 
278
      struct grub_acpi_table_header *rsdt;
 
279
      grub_uint32_t *entry_ptr;
 
280
 
 
281
  rsdp2 = grub_acpi_get_rsdpv2 ();
 
282
  if (rsdp2)
 
283
    rsdp1 = &(rsdp2->rsdpv1);
 
284
  else
 
285
    rsdp1 = grub_acpi_get_rsdpv1 ();
 
286
  grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
 
287
  if (!rsdp1)
 
288
    return;
 
289
 
 
290
  rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr;
 
291
  for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
 
292
       entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
 
293
                                      + rsdt->length);
 
294
       entry_ptr++)
 
295
    {
 
296
      if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0)
 
297
        {
 
298
          grub_uint32_t port;
 
299
          struct grub_acpi_fadt *fadt
 
300
            = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr);
 
301
          struct grub_acpi_table_header *dsdt
 
302
            = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr;
 
303
          int sleep_type = -1;
 
304
 
 
305
          port = fadt->pm1a;
 
306
 
 
307
          grub_dprintf ("acpi", "PM1a port=%x\n", port);
 
308
 
 
309
          if (grub_memcmp (dsdt->signature, "DSDT",
 
310
                           sizeof (dsdt->signature)) != 0)
 
311
            break;
 
312
 
 
313
          sleep_type = get_sleep_type ((grub_uint8_t *) dsdt,
 
314
                                       (grub_uint8_t *) dsdt + dsdt->length);
 
315
 
 
316
          if (sleep_type < 0 || sleep_type >= 8)
 
317
            break;
 
318
 
 
319
          grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n",
 
320
                        sleep_type, port);
 
321
 
 
322
          grub_outw (GRUB_ACPI_SLP_EN
 
323
                     | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff);
 
324
        }
 
325
    }
 
326
 
 
327
  grub_printf ("ACPI shutdown failed\n");
 
328
}
 
329
#endif