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

« back to all changes in this revision

Viewing changes to grub-core/loader/multiboot.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
/* multiboot.c - boot a multiboot OS image. */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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
/*
 
21
 *  FIXME: The following features from the Multiboot specification still
 
22
 *         need to be implemented:
 
23
 *  - drives table
 
24
 *  - ROM configuration table
 
25
 *  - SMBIOS tables
 
26
 *  - Networking information
 
27
 */
 
28
 
 
29
#include <grub/loader.h>
 
30
#include <grub/command.h>
 
31
#include <grub/multiboot.h>
 
32
#include <grub/cpu/multiboot.h>
 
33
#include <grub/elf.h>
 
34
#include <grub/aout.h>
 
35
#include <grub/file.h>
 
36
#include <grub/err.h>
 
37
#include <grub/dl.h>
 
38
#include <grub/mm.h>
 
39
#include <grub/misc.h>
 
40
#include <grub/env.h>
 
41
#include <grub/cpu/relocator.h>
 
42
#include <grub/video.h>
 
43
#include <grub/memory.h>
 
44
#include <grub/i18n.h>
 
45
 
 
46
#ifdef GRUB_MACHINE_EFI
 
47
#include <grub/efi/efi.h>
 
48
#endif
 
49
 
 
50
struct grub_relocator *grub_multiboot_relocator = NULL;
 
51
grub_uint32_t grub_multiboot_payload_eip;
 
52
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
 
53
#define DEFAULT_VIDEO_MODE "text"
 
54
#else
 
55
#define DEFAULT_VIDEO_MODE "auto"
 
56
#endif
 
57
 
 
58
static int accepts_video;
 
59
static int accepts_ega_text;
 
60
static int console_required;
 
61
static grub_dl_t my_mod;
 
62
 
 
63
 
 
64
/* Return the length of the Multiboot mmap that will be needed to allocate
 
65
   our platform's map.  */
 
66
grub_uint32_t
 
67
grub_get_multiboot_mmap_count (void)
 
68
{
 
69
  grub_size_t count = 0;
 
70
 
 
71
  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
 
72
  int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
 
73
                             grub_uint64_t size __attribute__ ((unused)),
 
74
                             grub_memory_type_t type __attribute__ ((unused)))
 
75
    {
 
76
      count++;
 
77
      return 0;
 
78
    }
 
79
 
 
80
  grub_mmap_iterate (hook);
 
81
 
 
82
  return count;
 
83
}
 
84
 
 
85
grub_err_t
 
86
grub_multiboot_set_video_mode (void)
 
87
{
 
88
  grub_err_t err;
 
89
  const char *modevar;
 
90
 
 
91
  if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT)
 
92
    {
 
93
      modevar = grub_env_get ("gfxpayload");
 
94
      if (! modevar || *modevar == 0)
 
95
        err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
 
96
      else
 
97
        {
 
98
          char *tmp;
 
99
          tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
 
100
          if (! tmp)
 
101
            return grub_errno;
 
102
          err = grub_video_set_mode (tmp, 0, 0);
 
103
          grub_free (tmp);
 
104
        }
 
105
    }
 
106
  else
 
107
    err = grub_video_set_mode ("text", 0, 0);
 
108
 
 
109
  return err;
 
110
}
 
111
 
 
112
static grub_err_t
 
113
grub_multiboot_boot (void)
 
114
{
 
115
  grub_err_t err;
 
116
  struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE;
 
117
 
 
118
  state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip;
 
119
 
 
120
  err = grub_multiboot_make_mbi (&state.MULTIBOOT_MBI_REGISTER);
 
121
 
 
122
  if (err)
 
123
    return err;
 
124
 
 
125
#ifdef GRUB_MACHINE_EFI
 
126
  err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
 
127
  if (err)
 
128
    return err;
 
129
#endif
 
130
 
 
131
  grub_relocator32_boot (grub_multiboot_relocator, state);
 
132
 
 
133
  /* Not reached.  */
 
134
  return GRUB_ERR_NONE;
 
135
}
 
136
 
 
137
static grub_err_t
 
138
grub_multiboot_unload (void)
 
139
{
 
140
  grub_multiboot_free_mbi ();
 
141
 
 
142
  grub_relocator_unload (grub_multiboot_relocator);
 
143
  grub_multiboot_relocator = NULL;
 
144
 
 
145
  grub_dl_unref (my_mod);
 
146
 
 
147
  return GRUB_ERR_NONE;
 
148
}
 
149
 
 
150
#define MULTIBOOT_LOAD_ELF64
 
151
#include "multiboot_elfxx.c"
 
152
#undef MULTIBOOT_LOAD_ELF64
 
153
 
 
154
#define MULTIBOOT_LOAD_ELF32
 
155
#include "multiboot_elfxx.c"
 
156
#undef MULTIBOOT_LOAD_ELF32
 
157
 
 
158
/* Load ELF32 or ELF64.  */
 
159
grub_err_t
 
160
grub_multiboot_load_elf (grub_file_t file, void *buffer)
 
161
{
 
162
  if (grub_multiboot_is_elf32 (buffer))
 
163
    return grub_multiboot_load_elf32 (file, buffer);
 
164
  else if (grub_multiboot_is_elf64 (buffer))
 
165
    return grub_multiboot_load_elf64 (file, buffer);
 
166
 
 
167
  return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
 
168
}
 
169
 
 
170
grub_err_t
 
171
grub_multiboot_set_console (int console_type, int accepted_consoles,
 
172
                            int width, int height, int depth,
 
173
                            int console_req)
 
174
{
 
175
  console_required = console_req;
 
176
  if (!(accepted_consoles 
 
177
        & (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
 
178
           | (GRUB_MACHINE_HAS_VGA_TEXT ? GRUB_MULTIBOOT_CONSOLE_EGA_TEXT : 0))))
 
179
    {
 
180
      if (console_required)
 
181
        return grub_error (GRUB_ERR_BAD_OS,
 
182
                           "OS requires a console but none is available");
 
183
      grub_printf ("WARNING: no console will be available to OS");
 
184
      accepts_video = 0;
 
185
      accepts_ega_text = 0;
 
186
      return GRUB_ERR_NONE;
 
187
    }
 
188
 
 
189
  if (console_type == GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER)
 
190
    {
 
191
      char *buf;
 
192
      if (depth && width && height)
 
193
        buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", width,
 
194
                              height, depth, width, height);
 
195
      else if (width && height)
 
196
        buf = grub_xasprintf ("%dx%d,auto", width, height);
 
197
      else
 
198
        buf = grub_strdup ("auto");
 
199
 
 
200
      if (!buf)
 
201
        return grub_errno;
 
202
      grub_env_set ("gfxpayload", buf);
 
203
      grub_free (buf);
 
204
    }
 
205
 else
 
206
   grub_env_set ("gfxpayload", "text");
 
207
 
 
208
  accepts_video = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER);
 
209
  accepts_ega_text = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_EGA_TEXT);
 
210
  return GRUB_ERR_NONE;
 
211
}
 
212
 
 
213
static grub_err_t
 
214
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
 
215
                    int argc, char *argv[])
 
216
{
 
217
  grub_file_t file = 0;
 
218
  grub_err_t err;
 
219
 
 
220
  grub_loader_unset ();
 
221
 
 
222
  if (argc == 0)
 
223
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
 
224
 
 
225
  file = grub_file_open (argv[0]);
 
226
  if (! file)
 
227
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
 
228
 
 
229
  grub_dl_ref (my_mod);
 
230
 
 
231
  /* Skip filename.  */
 
232
  grub_multiboot_init_mbi (argc - 1, argv + 1);
 
233
 
 
234
  grub_relocator_unload (grub_multiboot_relocator);
 
235
  grub_multiboot_relocator = grub_relocator_new ();
 
236
 
 
237
  if (!grub_multiboot_relocator)
 
238
    goto fail;
 
239
 
 
240
  err = grub_multiboot_load (file);
 
241
  if (err)
 
242
    goto fail;
 
243
 
 
244
  grub_multiboot_set_bootdev ();
 
245
 
 
246
  grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
 
247
 
 
248
 fail:
 
249
  if (file)
 
250
    grub_file_close (file);
 
251
 
 
252
  if (grub_errno != GRUB_ERR_NONE)
 
253
    {
 
254
      grub_relocator_unload (grub_multiboot_relocator);
 
255
      grub_multiboot_relocator = NULL;
 
256
      grub_dl_unref (my_mod);
 
257
    }
 
258
 
 
259
  return grub_errno;
 
260
}
 
261
 
 
262
static grub_err_t
 
263
grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
 
264
                 int argc, char *argv[])
 
265
{
 
266
  grub_file_t file = 0;
 
267
  grub_ssize_t size;
 
268
  void *module = NULL;
 
269
  grub_addr_t target;
 
270
  grub_err_t err;
 
271
  int nounzip = 0;
 
272
 
 
273
  if (argc == 0)
 
274
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
 
275
 
 
276
  if (grub_strcmp (argv[0], "--nounzip") == 0)
 
277
    {
 
278
      argv++;
 
279
      argc--;
 
280
      nounzip = 1;
 
281
    }
 
282
 
 
283
  if (argc == 0)
 
284
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
 
285
 
 
286
  if (!grub_multiboot_relocator)
 
287
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
 
288
                       "you need to load the multiboot kernel first");
 
289
 
 
290
  if (nounzip)
 
291
    grub_file_filter_disable_compression ();
 
292
 
 
293
  file = grub_file_open (argv[0]);
 
294
  if (! file)
 
295
    return grub_errno;
 
296
 
 
297
  size = grub_file_size (file);
 
298
  {
 
299
    grub_relocator_chunk_t ch;
 
300
    err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
 
301
                                            0, (0xffffffff - size) + 1,
 
302
                                            size, MULTIBOOT_MOD_ALIGN,
 
303
                                            GRUB_RELOCATOR_PREFERENCE_NONE);
 
304
    if (err)
 
305
      {
 
306
        grub_file_close (file);
 
307
        return err;
 
308
      }
 
309
    module = get_virtual_current_address (ch);
 
310
    target = (grub_addr_t) get_virtual_current_address (ch);
 
311
  }
 
312
 
 
313
  err = grub_multiboot_add_module (target, size, argc - 1, argv + 1);
 
314
  if (err)
 
315
    {
 
316
      grub_file_close (file);
 
317
      return err;
 
318
    }
 
319
 
 
320
  if (grub_file_read (file, module, size) != size)
 
321
    {
 
322
      grub_file_close (file);
 
323
      return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
 
324
    }
 
325
 
 
326
  grub_file_close (file);
 
327
  return GRUB_ERR_NONE;;
 
328
}
 
329
 
 
330
static grub_command_t cmd_multiboot, cmd_module;
 
331
 
 
332
GRUB_MOD_INIT(multiboot)
 
333
{
 
334
  cmd_multiboot =
 
335
#ifdef GRUB_USE_MULTIBOOT2
 
336
    grub_register_command ("multiboot2", grub_cmd_multiboot,
 
337
                           0, N_("Load a multiboot 2 kernel."));
 
338
  cmd_module =
 
339
    grub_register_command ("module2", grub_cmd_module,
 
340
                           0, N_("Load a multiboot 2 module."));
 
341
#else
 
342
    grub_register_command ("multiboot", grub_cmd_multiboot,
 
343
                           0, N_("Load a multiboot kernel."));
 
344
  cmd_module =
 
345
    grub_register_command ("module", grub_cmd_module,
 
346
                           0, N_("Load a multiboot module."));
 
347
#endif
 
348
 
 
349
  my_mod = mod;
 
350
}
 
351
 
 
352
GRUB_MOD_FINI(multiboot)
 
353
{
 
354
  grub_unregister_command (cmd_multiboot);
 
355
  grub_unregister_command (cmd_module);
 
356
}