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

« back to all changes in this revision

Viewing changes to kern/efi/efi.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
 
/* efi.c - generic EFI support */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2006,2007,2008,2009,2010  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/misc.h>
21
 
#include <grub/charset.h>
22
 
#include <grub/efi/api.h>
23
 
#include <grub/efi/efi.h>
24
 
#include <grub/efi/console_control.h>
25
 
#include <grub/efi/pe32.h>
26
 
#include <grub/machine/time.h>
27
 
#include <grub/term.h>
28
 
#include <grub/kernel.h>
29
 
#include <grub/mm.h>
30
 
 
31
 
/* The handle of GRUB itself. Filled in by the startup code.  */
32
 
grub_efi_handle_t grub_efi_image_handle;
33
 
 
34
 
/* The pointer to a system table. Filled in by the startup code.  */
35
 
grub_efi_system_table_t *grub_efi_system_table;
36
 
 
37
 
static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
38
 
static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
39
 
static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
40
 
 
41
 
void *
42
 
grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
43
 
{
44
 
  void *interface;
45
 
  grub_efi_status_t status;
46
 
 
47
 
  status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
48
 
                       protocol, registration, &interface);
49
 
  if (status != GRUB_EFI_SUCCESS)
50
 
    return 0;
51
 
 
52
 
  return interface;
53
 
}
54
 
 
55
 
/* Return the array of handles which meet the requirement. If successful,
56
 
   the number of handles is stored in NUM_HANDLES. The array is allocated
57
 
   from the heap.  */
58
 
grub_efi_handle_t *
59
 
grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
60
 
                        grub_efi_guid_t *protocol,
61
 
                        void *search_key,
62
 
                        grub_efi_uintn_t *num_handles)
63
 
{
64
 
  grub_efi_boot_services_t *b;
65
 
  grub_efi_status_t status;
66
 
  grub_efi_handle_t *buffer;
67
 
  grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);
68
 
 
69
 
  buffer = grub_malloc (buffer_size);
70
 
  if (! buffer)
71
 
    return 0;
72
 
 
73
 
  b = grub_efi_system_table->boot_services;
74
 
  status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
75
 
                             &buffer_size, buffer);
76
 
  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
77
 
    {
78
 
      grub_free (buffer);
79
 
      buffer = grub_malloc (buffer_size);
80
 
      if (! buffer)
81
 
        return 0;
82
 
 
83
 
      status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
84
 
                                 &buffer_size, buffer);
85
 
    }
86
 
 
87
 
  if (status != GRUB_EFI_SUCCESS)
88
 
    {
89
 
      grub_free (buffer);
90
 
      return 0;
91
 
    }
92
 
 
93
 
  *num_handles = buffer_size / sizeof (grub_efi_handle_t);
94
 
  return buffer;
95
 
}
96
 
 
97
 
void *
98
 
grub_efi_open_protocol (grub_efi_handle_t handle,
99
 
                        grub_efi_guid_t *protocol,
100
 
                        grub_efi_uint32_t attributes)
101
 
{
102
 
  grub_efi_boot_services_t *b;
103
 
  grub_efi_status_t status;
104
 
  void *interface;
105
 
 
106
 
  b = grub_efi_system_table->boot_services;
107
 
  status = efi_call_6 (b->open_protocol, handle,
108
 
                       protocol,
109
 
                       &interface,
110
 
                       grub_efi_image_handle,
111
 
                       0,
112
 
                       attributes);
113
 
  if (status != GRUB_EFI_SUCCESS)
114
 
    return 0;
115
 
 
116
 
  return interface;
117
 
}
118
 
 
119
 
int
120
 
grub_efi_set_text_mode (int on)
121
 
{
122
 
  grub_efi_console_control_protocol_t *c;
123
 
  grub_efi_screen_mode_t mode, new_mode;
124
 
 
125
 
  c = grub_efi_locate_protocol (&console_control_guid, 0);
126
 
  if (! c)
127
 
    /* No console control protocol instance available, assume it is
128
 
       already in text mode. */
129
 
    return 1;
130
 
 
131
 
  if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
132
 
    return 0;
133
 
 
134
 
  new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
135
 
  if (mode != new_mode)
136
 
    if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS)
137
 
      return 0;
138
 
 
139
 
  return 1;
140
 
}
141
 
 
142
 
void
143
 
grub_efi_stall (grub_efi_uintn_t microseconds)
144
 
{
145
 
  efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
146
 
}
147
 
 
148
 
grub_efi_loaded_image_t *
149
 
grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
150
 
{
151
 
  return grub_efi_open_protocol (image_handle,
152
 
                                 &loaded_image_guid,
153
 
                                 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
154
 
}
155
 
 
156
 
void
157
 
grub_exit (void)
158
 
{
159
 
  grub_efi_fini ();
160
 
  efi_call_4 (grub_efi_system_table->boot_services->exit,
161
 
              grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
162
 
  for (;;) ;
163
 
}
164
 
 
165
 
/* On i386, a firmware-independant grub_reboot() is provided by realmode.S.  */
166
 
#ifndef __i386__
167
 
void
168
 
grub_reboot (void)
169
 
{
170
 
  grub_efi_fini ();
171
 
  efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
172
 
              GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
173
 
  for (;;) ;
174
 
}
175
 
#endif
176
 
 
177
 
void
178
 
grub_halt (void)
179
 
{
180
 
  grub_efi_fini ();
181
 
  efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
182
 
              GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
183
 
  for (;;) ;
184
 
}
185
 
 
186
 
int
187
 
grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
188
 
{
189
 
  grub_efi_boot_services_t *b;
190
 
  grub_efi_status_t status;
191
 
 
192
 
  b = grub_efi_system_table->boot_services;
193
 
  status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key);
194
 
  return status == GRUB_EFI_SUCCESS;
195
 
}
196
 
 
197
 
grub_err_t
198
 
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
199
 
                                  grub_efi_uintn_t descriptor_size,
200
 
                                  grub_efi_uint32_t descriptor_version,
201
 
                                  grub_efi_memory_descriptor_t *virtual_map)
202
 
{
203
 
  grub_efi_runtime_services_t *r;
204
 
  grub_efi_status_t status;
205
 
 
206
 
  r = grub_efi_system_table->runtime_services;
207
 
  status = efi_call_4 (r->set_virtual_address_map, memory_map_size,
208
 
                       descriptor_size, descriptor_version, virtual_map);
209
 
 
210
 
  if (status == GRUB_EFI_SUCCESS)
211
 
    return GRUB_ERR_NONE;
212
 
 
213
 
  return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
214
 
}
215
 
 
216
 
grub_uint32_t
217
 
grub_get_rtc (void)
218
 
{
219
 
  grub_efi_time_t time;
220
 
  grub_efi_runtime_services_t *r;
221
 
 
222
 
  r = grub_efi_system_table->runtime_services;
223
 
  if (efi_call_2 (r->get_time, &time, 0) != GRUB_EFI_SUCCESS)
224
 
    /* What is possible in this case?  */
225
 
    return 0;
226
 
 
227
 
  return (((time.minute * 60 + time.second) * 1000
228
 
           + time.nanosecond / 1000000)
229
 
          * GRUB_TICKS_PER_SECOND / 1000);
230
 
}
231
 
 
232
 
/* Search the mods section from the PE32/PE32+ image. This code uses
233
 
   a PE32 header, but should work with PE32+ as well.  */
234
 
grub_addr_t
235
 
grub_arch_modules_addr (void)
236
 
{
237
 
  grub_efi_loaded_image_t *image;
238
 
  struct grub_pe32_header *header;
239
 
  struct grub_pe32_coff_header *coff_header;
240
 
  struct grub_pe32_section_table *sections;
241
 
  struct grub_pe32_section_table *section;
242
 
  struct grub_module_info *info;
243
 
  grub_uint16_t i;
244
 
 
245
 
  image = grub_efi_get_loaded_image (grub_efi_image_handle);
246
 
  if (! image)
247
 
    return 0;
248
 
 
249
 
  header = image->image_base;
250
 
  coff_header = &(header->coff_header);
251
 
  sections
252
 
    = (struct grub_pe32_section_table *) ((char *) coff_header
253
 
                                          + sizeof (*coff_header)
254
 
                                          + coff_header->optional_header_size);
255
 
 
256
 
  for (i = 0, section = sections;
257
 
       i < coff_header->num_sections;
258
 
       i++, section++)
259
 
    {
260
 
      if (grub_strcmp (section->name, "mods") == 0)
261
 
        break;
262
 
    }
263
 
 
264
 
  if (i == coff_header->num_sections)
265
 
    return 0;
266
 
 
267
 
  info = (struct grub_module_info *) ((char *) image->image_base
268
 
                                      + section->virtual_address);
269
 
  if (info->magic != GRUB_MODULE_MAGIC)
270
 
    return 0;
271
 
 
272
 
  return (grub_addr_t) info;
273
 
}
274
 
 
275
 
char *
276
 
grub_efi_get_filename (grub_efi_device_path_t *dp)
277
 
{
278
 
  char *name = 0;
279
 
 
280
 
  while (1)
281
 
    {
282
 
      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
283
 
      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
284
 
 
285
 
      if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
286
 
        break;
287
 
      else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
288
 
               && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
289
 
        {
290
 
          grub_efi_file_path_device_path_t *fp;
291
 
          grub_efi_uint16_t len;
292
 
          char *p;
293
 
          grub_size_t size;
294
 
 
295
 
          if (name)
296
 
            {
297
 
              size = grub_strlen (name);
298
 
              name[size] = '/';
299
 
              size++;
300
 
            }
301
 
          else
302
 
            size = 0;
303
 
 
304
 
          len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
305
 
                 / sizeof (grub_efi_char16_t));
306
 
          p = grub_realloc (name, size + len * 4 + 1);
307
 
          if (! p)
308
 
            {
309
 
              grub_free (name);
310
 
              return 0;
311
 
            }
312
 
 
313
 
          name = p;
314
 
          fp = (grub_efi_file_path_device_path_t *) dp;
315
 
          *grub_utf16_to_utf8 ((grub_uint8_t *) name + size,
316
 
                               fp->path_name, len) = '\0';
317
 
        }
318
 
 
319
 
      dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
320
 
    }
321
 
 
322
 
  if (name)
323
 
    {
324
 
      /* EFI breaks paths with backslashes.  */
325
 
      char *p;
326
 
 
327
 
      for (p = name; *p; p++)
328
 
        if (*p == '\\')
329
 
          *p = '/';
330
 
    }
331
 
 
332
 
  return name;
333
 
}
334
 
 
335
 
grub_efi_device_path_t *
336
 
grub_efi_get_device_path (grub_efi_handle_t handle)
337
 
{
338
 
  return grub_efi_open_protocol (handle, &device_path_guid,
339
 
                                 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
340
 
}
341
 
 
342
 
/* Print the chain of Device Path nodes. This is mainly for debugging. */
343
 
void
344
 
grub_efi_print_device_path (grub_efi_device_path_t *dp)
345
 
{
346
 
  while (1)
347
 
    {
348
 
      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
349
 
      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
350
 
      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
351
 
 
352
 
      switch (type)
353
 
        {
354
 
        case GRUB_EFI_END_DEVICE_PATH_TYPE:
355
 
          switch (subtype)
356
 
            {
357
 
            case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
358
 
              grub_printf ("/EndEntire\n");
359
 
              //grub_putchar ('\n');
360
 
              break;
361
 
            case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
362
 
              grub_printf ("/EndThis\n");
363
 
              //grub_putchar ('\n');
364
 
              break;
365
 
            default:
366
 
              grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
367
 
              break;
368
 
            }
369
 
          break;
370
 
 
371
 
        case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
372
 
          switch (subtype)
373
 
            {
374
 
            case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
375
 
              {
376
 
                grub_efi_pci_device_path_t pci;
377
 
                grub_memcpy (&pci, dp, len);
378
 
                grub_printf ("/PCI(%x,%x)",
379
 
                             (unsigned) pci.function, (unsigned) pci.device);
380
 
              }
381
 
              break;
382
 
            case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
383
 
              {
384
 
                grub_efi_pccard_device_path_t pccard;
385
 
                grub_memcpy (&pccard, dp, len);
386
 
                grub_printf ("/PCCARD(%x)",
387
 
                             (unsigned) pccard.function);
388
 
              }
389
 
              break;
390
 
            case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
391
 
              {
392
 
                grub_efi_memory_mapped_device_path_t mmapped;
393
 
                grub_memcpy (&mmapped, dp, len);
394
 
                grub_printf ("/MMap(%x,%llx,%llx)",
395
 
                             (unsigned) mmapped.memory_type,
396
 
                             (unsigned long long) mmapped.start_address,
397
 
                             (unsigned long long) mmapped.end_address);
398
 
              }
399
 
              break;
400
 
            case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
401
 
              {
402
 
                grub_efi_vendor_device_path_t vendor;
403
 
                grub_memcpy (&vendor, dp, sizeof (vendor));
404
 
                grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
405
 
                             (unsigned) vendor.vendor_guid.data1,
406
 
                             (unsigned) vendor.vendor_guid.data2,
407
 
                             (unsigned) vendor.vendor_guid.data3,
408
 
                             (unsigned) vendor.vendor_guid.data4[0],
409
 
                             (unsigned) vendor.vendor_guid.data4[1],
410
 
                             (unsigned) vendor.vendor_guid.data4[2],
411
 
                             (unsigned) vendor.vendor_guid.data4[3],
412
 
                             (unsigned) vendor.vendor_guid.data4[4],
413
 
                             (unsigned) vendor.vendor_guid.data4[5],
414
 
                             (unsigned) vendor.vendor_guid.data4[6],
415
 
                             (unsigned) vendor.vendor_guid.data4[7]);
416
 
              }
417
 
              break;
418
 
            case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
419
 
              {
420
 
                grub_efi_controller_device_path_t controller;
421
 
                grub_memcpy (&controller, dp, len);
422
 
                grub_printf ("/Ctrl(%x)",
423
 
                             (unsigned) controller.controller_number);
424
 
              }
425
 
              break;
426
 
            default:
427
 
              grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
428
 
              break;
429
 
            }
430
 
          break;
431
 
 
432
 
        case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
433
 
          switch (subtype)
434
 
            {
435
 
            case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
436
 
              {
437
 
                grub_efi_acpi_device_path_t acpi;
438
 
                grub_memcpy (&acpi, dp, len);
439
 
                grub_printf ("/ACPI(%x,%x)",
440
 
                             (unsigned) acpi.hid,
441
 
                             (unsigned) acpi.uid);
442
 
              }
443
 
              break;
444
 
            case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
445
 
              {
446
 
                grub_efi_expanded_acpi_device_path_t eacpi;
447
 
                grub_memcpy (&eacpi, dp, sizeof (eacpi));
448
 
                grub_printf ("/ACPI(");
449
 
 
450
 
                if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
451
 
                  grub_printf ("%x,", (unsigned) eacpi.hid);
452
 
                else
453
 
                  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
454
 
 
455
 
                if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
456
 
                  grub_printf ("%x,", (unsigned) eacpi.uid);
457
 
                else
458
 
                  grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
459
 
 
460
 
                if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
461
 
                  grub_printf ("%x)", (unsigned) eacpi.cid);
462
 
                else
463
 
                  grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
464
 
              }
465
 
              break;
466
 
            default:
467
 
              grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
468
 
              break;
469
 
            }
470
 
          break;
471
 
 
472
 
        case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
473
 
          switch (subtype)
474
 
            {
475
 
            case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
476
 
              {
477
 
                grub_efi_atapi_device_path_t atapi;
478
 
                grub_memcpy (&atapi, dp, len);
479
 
                grub_printf ("/ATAPI(%x,%x,%x)",
480
 
                             (unsigned) atapi.primary_secondary,
481
 
                             (unsigned) atapi.slave_master,
482
 
                             (unsigned) atapi.lun);
483
 
              }
484
 
              break;
485
 
            case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
486
 
              {
487
 
                grub_efi_scsi_device_path_t scsi;
488
 
                grub_memcpy (&scsi, dp, len);
489
 
                grub_printf ("/SCSI(%x,%x)",
490
 
                             (unsigned) scsi.pun,
491
 
                             (unsigned) scsi.lun);
492
 
              }
493
 
              break;
494
 
            case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
495
 
              {
496
 
                grub_efi_fibre_channel_device_path_t fc;
497
 
                grub_memcpy (&fc, dp, len);
498
 
                grub_printf ("/FibreChannel(%llx,%llx)",
499
 
                             (unsigned long long) fc.wwn,
500
 
                             (unsigned long long) fc.lun);
501
 
              }
502
 
              break;
503
 
            case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
504
 
              {
505
 
                grub_efi_1394_device_path_t firewire;
506
 
                grub_memcpy (&firewire, dp, len);
507
 
                grub_printf ("/1394(%llx)", (unsigned long long) firewire.guid);
508
 
              }
509
 
              break;
510
 
            case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
511
 
              {
512
 
                grub_efi_usb_device_path_t usb;
513
 
                grub_memcpy (&usb, dp, len);
514
 
                grub_printf ("/USB(%x,%x)",
515
 
                             (unsigned) usb.parent_port_number,
516
 
                             (unsigned) usb.interface);
517
 
              }
518
 
              break;
519
 
            case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
520
 
              {
521
 
                grub_efi_usb_class_device_path_t usb_class;
522
 
                grub_memcpy (&usb_class, dp, len);
523
 
                grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
524
 
                             (unsigned) usb_class.vendor_id,
525
 
                             (unsigned) usb_class.product_id,
526
 
                             (unsigned) usb_class.device_class,
527
 
                             (unsigned) usb_class.device_subclass,
528
 
                             (unsigned) usb_class.device_protocol);
529
 
              }
530
 
              break;
531
 
            case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
532
 
              {
533
 
                grub_efi_i2o_device_path_t i2o;
534
 
                grub_memcpy (&i2o, dp, len);
535
 
                grub_printf ("/I2O(%x)", (unsigned) i2o.tid);
536
 
              }
537
 
              break;
538
 
            case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
539
 
              {
540
 
                grub_efi_mac_address_device_path_t mac;
541
 
                grub_memcpy (&mac, dp, len);
542
 
                grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
543
 
                             (unsigned) mac.mac_address[0],
544
 
                             (unsigned) mac.mac_address[1],
545
 
                             (unsigned) mac.mac_address[2],
546
 
                             (unsigned) mac.mac_address[3],
547
 
                             (unsigned) mac.mac_address[4],
548
 
                             (unsigned) mac.mac_address[5],
549
 
                             (unsigned) mac.if_type);
550
 
              }
551
 
              break;
552
 
            case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
553
 
              {
554
 
                grub_efi_ipv4_device_path_t ipv4;
555
 
                grub_memcpy (&ipv4, dp, len);
556
 
                grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
557
 
                             (unsigned) ipv4.local_ip_address[0],
558
 
                             (unsigned) ipv4.local_ip_address[1],
559
 
                             (unsigned) ipv4.local_ip_address[2],
560
 
                             (unsigned) ipv4.local_ip_address[3],
561
 
                             (unsigned) ipv4.remote_ip_address[0],
562
 
                             (unsigned) ipv4.remote_ip_address[1],
563
 
                             (unsigned) ipv4.remote_ip_address[2],
564
 
                             (unsigned) ipv4.remote_ip_address[3],
565
 
                             (unsigned) ipv4.local_port,
566
 
                             (unsigned) ipv4.remote_port,
567
 
                             (unsigned) ipv4.protocol,
568
 
                             (unsigned) ipv4.static_ip_address);
569
 
              }
570
 
              break;
571
 
            case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
572
 
              {
573
 
                grub_efi_ipv6_device_path_t ipv6;
574
 
                grub_memcpy (&ipv6, dp, len);
575
 
                grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
576
 
                             (unsigned) ipv6.local_ip_address[0],
577
 
                             (unsigned) ipv6.local_ip_address[1],
578
 
                             (unsigned) ipv6.local_ip_address[2],
579
 
                             (unsigned) ipv6.local_ip_address[3],
580
 
                             (unsigned) ipv6.local_ip_address[4],
581
 
                             (unsigned) ipv6.local_ip_address[5],
582
 
                             (unsigned) ipv6.local_ip_address[6],
583
 
                             (unsigned) ipv6.local_ip_address[7],
584
 
                             (unsigned) ipv6.remote_ip_address[0],
585
 
                             (unsigned) ipv6.remote_ip_address[1],
586
 
                             (unsigned) ipv6.remote_ip_address[2],
587
 
                             (unsigned) ipv6.remote_ip_address[3],
588
 
                             (unsigned) ipv6.remote_ip_address[4],
589
 
                             (unsigned) ipv6.remote_ip_address[5],
590
 
                             (unsigned) ipv6.remote_ip_address[6],
591
 
                             (unsigned) ipv6.remote_ip_address[7],
592
 
                             (unsigned) ipv6.local_port,
593
 
                             (unsigned) ipv6.remote_port,
594
 
                             (unsigned) ipv6.protocol,
595
 
                             (unsigned) ipv6.static_ip_address);
596
 
              }
597
 
              break;
598
 
            case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
599
 
              {
600
 
                grub_efi_infiniband_device_path_t ib;
601
 
                grub_memcpy (&ib, dp, len);
602
 
                grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
603
 
                             (unsigned) ib.port_gid[0], /* XXX */
604
 
                             (unsigned long long) ib.remote_id,
605
 
                             (unsigned long long) ib.target_port_id,
606
 
                             (unsigned long long) ib.device_id);
607
 
              }
608
 
              break;
609
 
            case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
610
 
              {
611
 
                grub_efi_uart_device_path_t uart;
612
 
                grub_memcpy (&uart, dp, len);
613
 
                grub_printf ("/UART(%llu,%u,%x,%x)",
614
 
                             (unsigned long long) uart.baud_rate,
615
 
                             uart.data_bits,
616
 
                             uart.parity,
617
 
                             uart.stop_bits);
618
 
              }
619
 
              break;
620
 
            case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
621
 
              {
622
 
                grub_efi_vendor_messaging_device_path_t vendor;
623
 
                grub_memcpy (&vendor, dp, sizeof (vendor));
624
 
                grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
625
 
                             (unsigned) vendor.vendor_guid.data1,
626
 
                             (unsigned) vendor.vendor_guid.data2,
627
 
                             (unsigned) vendor.vendor_guid.data3,
628
 
                             (unsigned) vendor.vendor_guid.data4[0],
629
 
                             (unsigned) vendor.vendor_guid.data4[1],
630
 
                             (unsigned) vendor.vendor_guid.data4[2],
631
 
                             (unsigned) vendor.vendor_guid.data4[3],
632
 
                             (unsigned) vendor.vendor_guid.data4[4],
633
 
                             (unsigned) vendor.vendor_guid.data4[5],
634
 
                             (unsigned) vendor.vendor_guid.data4[6],
635
 
                             (unsigned) vendor.vendor_guid.data4[7]);
636
 
              }
637
 
              break;
638
 
            default:
639
 
              grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
640
 
              break;
641
 
            }
642
 
          break;
643
 
 
644
 
        case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
645
 
          switch (subtype)
646
 
            {
647
 
            case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
648
 
              {
649
 
                grub_efi_hard_drive_device_path_t hd;
650
 
                grub_memcpy (&hd, dp, len);
651
 
                grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
652
 
                             hd.partition_number,
653
 
                             (unsigned long long) hd.partition_start,
654
 
                             (unsigned long long) hd.partition_size,
655
 
                             (unsigned) hd.partition_signature[0],
656
 
                             (unsigned) hd.partition_signature[1],
657
 
                             (unsigned) hd.partition_signature[2],
658
 
                             (unsigned) hd.partition_signature[3],
659
 
                             (unsigned) hd.partition_signature[4],
660
 
                             (unsigned) hd.partition_signature[5],
661
 
                             (unsigned) hd.partition_signature[6],
662
 
                             (unsigned) hd.partition_signature[7],
663
 
                             (unsigned) hd.mbr_type,
664
 
                             (unsigned) hd.signature_type);
665
 
              }
666
 
              break;
667
 
            case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
668
 
              {
669
 
                grub_efi_cdrom_device_path_t cd;
670
 
                grub_memcpy (&cd, dp, len);
671
 
                grub_printf ("/CD(%u,%llx,%llx)",
672
 
                             cd.boot_entry,
673
 
                             (unsigned long long) cd.partition_start,
674
 
                             (unsigned long long) cd.partition_size);
675
 
              }
676
 
              break;
677
 
            case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
678
 
              {
679
 
                grub_efi_vendor_media_device_path_t vendor;
680
 
                grub_memcpy (&vendor, dp, sizeof (vendor));
681
 
                grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
682
 
                             (unsigned) vendor.vendor_guid.data1,
683
 
                             (unsigned) vendor.vendor_guid.data2,
684
 
                             (unsigned) vendor.vendor_guid.data3,
685
 
                             (unsigned) vendor.vendor_guid.data4[0],
686
 
                             (unsigned) vendor.vendor_guid.data4[1],
687
 
                             (unsigned) vendor.vendor_guid.data4[2],
688
 
                             (unsigned) vendor.vendor_guid.data4[3],
689
 
                             (unsigned) vendor.vendor_guid.data4[4],
690
 
                             (unsigned) vendor.vendor_guid.data4[5],
691
 
                             (unsigned) vendor.vendor_guid.data4[6],
692
 
                             (unsigned) vendor.vendor_guid.data4[7]);
693
 
              }
694
 
              break;
695
 
            case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
696
 
              {
697
 
                grub_efi_file_path_device_path_t *fp;
698
 
                grub_uint8_t buf[(len - 4) * 2 + 1];
699
 
                fp = (grub_efi_file_path_device_path_t *) dp;
700
 
                *grub_utf16_to_utf8 (buf, fp->path_name,
701
 
                                     (len - 4) / sizeof (grub_efi_char16_t))
702
 
                  = '\0';
703
 
                grub_printf ("/File(%s)", buf);
704
 
              }
705
 
              break;
706
 
            case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
707
 
              {
708
 
                grub_efi_protocol_device_path_t proto;
709
 
                grub_memcpy (&proto, dp, sizeof (proto));
710
 
                grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
711
 
                             (unsigned) proto.guid.data1,
712
 
                             (unsigned) proto.guid.data2,
713
 
                             (unsigned) proto.guid.data3,
714
 
                             (unsigned) proto.guid.data4[0],
715
 
                             (unsigned) proto.guid.data4[1],
716
 
                             (unsigned) proto.guid.data4[2],
717
 
                             (unsigned) proto.guid.data4[3],
718
 
                             (unsigned) proto.guid.data4[4],
719
 
                             (unsigned) proto.guid.data4[5],
720
 
                             (unsigned) proto.guid.data4[6],
721
 
                             (unsigned) proto.guid.data4[7]);
722
 
              }
723
 
              break;
724
 
            default:
725
 
              grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
726
 
              break;
727
 
            }
728
 
          break;
729
 
 
730
 
        case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
731
 
          switch (subtype)
732
 
            {
733
 
            case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
734
 
              {
735
 
                grub_efi_bios_device_path_t bios;
736
 
                grub_memcpy (&bios, dp, sizeof (bios));
737
 
                grub_printf ("/BIOS(%x,%x,%s)",
738
 
                             (unsigned) bios.device_type,
739
 
                             (unsigned) bios.status_flags,
740
 
                             (char *) (dp + 1));
741
 
              }
742
 
              break;
743
 
            default:
744
 
              grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
745
 
              break;
746
 
            }
747
 
          break;
748
 
 
749
 
        default:
750
 
          grub_printf ("/UnknownType(%x,%x)\n",
751
 
                       (unsigned) type,
752
 
                       (unsigned) subtype);
753
 
          return;
754
 
          break;
755
 
        }
756
 
 
757
 
      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
758
 
        break;
759
 
 
760
 
      dp = (grub_efi_device_path_t *) ((char *) dp + len);
761
 
    }
762
 
}
763
 
 
764
 
int
765
 
grub_efi_finish_boot_services (void)
766
 
{
767
 
  grub_efi_uintn_t mmap_size = 0;
768
 
  grub_efi_uintn_t map_key;
769
 
  grub_efi_uintn_t desc_size;
770
 
  grub_efi_uint32_t desc_version;
771
 
  void *mmap_buf = 0;
772
 
 
773
 
  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
774
 
                               &desc_size, &desc_version) < 0)
775
 
    return 0;
776
 
 
777
 
  mmap_buf = grub_malloc (mmap_size);
778
 
 
779
 
  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
780
 
                               &desc_size, &desc_version) <= 0)
781
 
    return 0;
782
 
 
783
 
  return grub_efi_exit_boot_services (map_key);
784
 
}
785