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

« back to all changes in this revision

Viewing changes to grub-core/loader/multiboot_mbi2.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) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009  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
#include <grub/memory.h>
 
20
#ifdef GRUB_MACHINE_PCBIOS
 
21
#include <grub/machine/biosnum.h>
 
22
#include <grub/machine/apm.h>
 
23
#include <grub/machine/memory.h>
 
24
#endif
 
25
#include <grub/multiboot.h>
 
26
#include <grub/cpu/multiboot.h>
 
27
#include <grub/cpu/relocator.h>
 
28
#include <grub/disk.h>
 
29
#include <grub/device.h>
 
30
#include <grub/partition.h>
 
31
#include <grub/mm.h>
 
32
#include <grub/misc.h>
 
33
#include <grub/env.h>
 
34
#include <grub/video.h>
 
35
#include <grub/acpi.h>
 
36
 
 
37
#if defined (GRUB_MACHINE_EFI)
 
38
#include <grub/efi/efi.h>
 
39
#endif
 
40
 
 
41
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
 
42
#include <grub/i386/pc/vbe.h>
 
43
#define HAS_VGA_TEXT 1
 
44
#else
 
45
#define HAS_VGA_TEXT 0
 
46
#endif
 
47
 
 
48
struct module
 
49
{
 
50
  struct module *next;
 
51
  grub_addr_t start;
 
52
  grub_size_t size;
 
53
  char *cmdline;
 
54
  int cmdline_size;
 
55
};
 
56
 
 
57
struct module *modules, *modules_last;
 
58
static grub_size_t cmdline_size;
 
59
static grub_size_t total_modcmd;
 
60
static unsigned modcnt;
 
61
static char *cmdline = NULL;
 
62
static int bootdev_set;
 
63
static grub_uint32_t biosdev, slice, part;
 
64
static grub_size_t elf_sec_num, elf_sec_entsize;
 
65
static unsigned elf_sec_shstrndx;
 
66
static void *elf_sections;
 
67
 
 
68
void
 
69
grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
 
70
                            unsigned shndx, void *data)
 
71
{
 
72
  elf_sec_num = num;
 
73
  elf_sec_shstrndx = shndx;
 
74
  elf_sec_entsize = entsize;
 
75
  elf_sections = data;
 
76
}
 
77
 
 
78
grub_err_t
 
79
grub_multiboot_load (grub_file_t file)
 
80
{
 
81
  char *buffer;
 
82
  grub_ssize_t len;
 
83
  struct multiboot_header *header;
 
84
  grub_err_t err;
 
85
  struct multiboot_header_tag *tag;
 
86
  struct multiboot_header_tag_address *addr_tag = NULL;
 
87
  int entry_specified = 0;
 
88
  grub_addr_t entry = 0;
 
89
  grub_uint32_t console_required = 0;
 
90
  struct multiboot_header_tag_framebuffer *fbtag = NULL;
 
91
  int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
 
92
 
 
93
  buffer = grub_malloc (MULTIBOOT_SEARCH);
 
94
  if (!buffer)
 
95
    return grub_errno;
 
96
 
 
97
  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
 
98
  if (len < 32)
 
99
    {
 
100
      grub_free (buffer);
 
101
      return grub_error (GRUB_ERR_BAD_OS, "file too small");
 
102
    }
 
103
 
 
104
  /* Look for the multiboot header in the buffer.  The header should
 
105
     be at least 12 bytes and aligned on a 4-byte boundary.  */
 
106
  for (header = (struct multiboot_header *) buffer;
 
107
       ((char *) header <= buffer + len - 12) || (header = 0);
 
108
       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
 
109
    {
 
110
      if (header->magic == MULTIBOOT_HEADER_MAGIC
 
111
          && !(header->magic + header->architecture
 
112
               + header->header_length + header->checksum)
 
113
          && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
 
114
        break;
 
115
    }
 
116
 
 
117
  if (header == 0)
 
118
    {
 
119
      grub_free (buffer);
 
120
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
 
121
    }
 
122
 
 
123
  for (tag = (struct multiboot_header_tag *) (header + 1);
 
124
       tag->type != MULTIBOOT_TAG_TYPE_END;
 
125
       tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
 
126
    switch (tag->type)
 
127
      {
 
128
      case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
 
129
        {
 
130
          unsigned i;
 
131
          struct multiboot_header_tag_information_request *request_tag
 
132
            = (struct multiboot_header_tag_information_request *) tag;
 
133
          if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
 
134
            break;
 
135
          for (i = 0; i < (request_tag->size - sizeof (request_tag))
 
136
                 / sizeof (request_tag->requests[0]); i++)
 
137
            switch (request_tag->requests[i])
 
138
              {
 
139
              case MULTIBOOT_TAG_TYPE_END:
 
140
              case MULTIBOOT_TAG_TYPE_CMDLINE:
 
141
              case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
 
142
              case MULTIBOOT_TAG_TYPE_MODULE:
 
143
              case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
 
144
              case MULTIBOOT_TAG_TYPE_BOOTDEV:
 
145
              case MULTIBOOT_TAG_TYPE_MMAP:
 
146
              case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
 
147
              case MULTIBOOT_TAG_TYPE_VBE:
 
148
              case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
 
149
              case MULTIBOOT_TAG_TYPE_APM:
 
150
              case MULTIBOOT_TAG_TYPE_EFI32:
 
151
              case MULTIBOOT_TAG_TYPE_EFI64:
 
152
              case MULTIBOOT_TAG_TYPE_ACPI_OLD:
 
153
              case MULTIBOOT_TAG_TYPE_ACPI_NEW:
 
154
                break;
 
155
 
 
156
              default:
 
157
                grub_free (buffer);
 
158
                return grub_error (GRUB_ERR_UNKNOWN_OS,
 
159
                                   "unsupported information tag: 0x%x",
 
160
                                   request_tag->requests[i]);
 
161
              }
 
162
          break;
 
163
        }
 
164
               
 
165
      case MULTIBOOT_HEADER_TAG_ADDRESS:
 
166
        addr_tag = (struct multiboot_header_tag_address *) tag;
 
167
        break;
 
168
 
 
169
      case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
 
170
        entry_specified = 1;
 
171
        entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
 
172
        break;
 
173
 
 
174
      case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
 
175
        if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
 
176
            & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
 
177
          accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
 
178
        if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
 
179
            & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
 
180
          console_required = 1;
 
181
        break;
 
182
 
 
183
      case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
 
184
        fbtag = (struct multiboot_header_tag_framebuffer *) tag;
 
185
        accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
 
186
        break;
 
187
 
 
188
        /* GRUB always page-aligns modules.  */
 
189
      case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
 
190
        break;
 
191
 
 
192
      default:
 
193
        if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
 
194
          {
 
195
            grub_free (buffer);
 
196
            return grub_error (GRUB_ERR_UNKNOWN_OS,
 
197
                               "unsupported tag: 0x%x", tag->type);
 
198
          }
 
199
        break;
 
200
      }
 
201
 
 
202
  if (addr_tag && !entry_specified)
 
203
    {
 
204
      grub_free (buffer);
 
205
      return grub_error (GRUB_ERR_UNKNOWN_OS,
 
206
                         "load address tag without entry address tag");
 
207
    }
 
208
 
 
209
  if (addr_tag)
 
210
    {
 
211
      int offset = ((char *) header - buffer -
 
212
                    (addr_tag->header_addr - addr_tag->load_addr));
 
213
      int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
 
214
                       addr_tag->load_end_addr - addr_tag->load_addr);
 
215
      grub_size_t code_size;
 
216
      void *source;
 
217
      grub_relocator_chunk_t ch;
 
218
 
 
219
      if (addr_tag->bss_end_addr)
 
220
        code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
 
221
      else
 
222
        code_size = load_size;
 
223
 
 
224
      err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, 
 
225
                                             &ch, addr_tag->load_addr,
 
226
                                             code_size);
 
227
      if (err)
 
228
        {
 
229
          grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
 
230
          grub_free (buffer);
 
231
          return err;
 
232
        }
 
233
      source = get_virtual_current_address (ch);
 
234
 
 
235
      if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
 
236
        {
 
237
          grub_free (buffer);
 
238
          return grub_errno;
 
239
        }
 
240
 
 
241
      grub_file_read (file, source, load_size);
 
242
      if (grub_errno)
 
243
        {
 
244
          grub_free (buffer);
 
245
          return grub_errno;
 
246
        }
 
247
 
 
248
      if (addr_tag->bss_end_addr)
 
249
        grub_memset ((grub_uint32_t *) source + load_size, 0,
 
250
                     addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
 
251
    }
 
252
  else
 
253
    {
 
254
      err = grub_multiboot_load_elf (file, buffer);
 
255
      if (err)
 
256
        {
 
257
          grub_free (buffer);
 
258
          return err;
 
259
        }
 
260
    }
 
261
 
 
262
  if (entry_specified)
 
263
    grub_multiboot_payload_eip = entry;
 
264
 
 
265
  if (fbtag)
 
266
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
 
267
                                      accepted_consoles,
 
268
                                      fbtag->width, fbtag->height,
 
269
                                      fbtag->depth, console_required);
 
270
  else
 
271
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
 
272
                                      accepted_consoles,
 
273
                                      0, 0, 0, console_required);
 
274
  return err;
 
275
}
 
276
 
 
277
static grub_size_t
 
278
acpiv2_size (void)
 
279
{
 
280
#if GRUB_MACHINE_HAS_ACPI
 
281
  struct grub_acpi_rsdp_v20 *p = grub_acpi_get_rsdpv2 ();
 
282
 
 
283
  if (!p)
 
284
    return 0;
 
285
 
 
286
  return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
 
287
                   + p->length, MULTIBOOT_TAG_ALIGN);
 
288
#else
 
289
  return 0;
 
290
#endif
 
291
}
 
292
 
 
293
static grub_size_t
 
294
grub_multiboot_get_mbi_size (void)
 
295
{
 
296
  return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
 
297
    + (sizeof (struct multiboot_tag_string)
 
298
       + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
 
299
    + (sizeof (struct multiboot_tag_string)
 
300
       + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
 
301
    + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
 
302
    + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo),
 
303
                MULTIBOOT_TAG_ALIGN)
 
304
    + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
 
305
    + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN)
 
306
    + ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN)
 
307
    + ALIGN_UP ((sizeof (struct multiboot_tag_mmap)
 
308
                 + grub_get_multiboot_mmap_count ()
 
309
                 * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
 
310
    + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
 
311
    + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
 
312
    + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
 
313
    + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
 
314
                + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
 
315
    + acpiv2_size ()
 
316
    + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1
 
317
    + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1;
 
318
}
 
319
 
 
320
/* Fill previously allocated Multiboot mmap.  */
 
321
static void
 
322
grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
 
323
{
 
324
  struct multiboot_mmap_entry *mmap_entry = tag->entries;
 
325
 
 
326
  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
 
327
                                  grub_memory_type_t);
 
328
  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
 
329
                             grub_memory_type_t type)
 
330
    {
 
331
      mmap_entry->addr = addr;
 
332
      mmap_entry->len = size;
 
333
      switch (type)
 
334
        {
 
335
        case GRUB_MEMORY_AVAILABLE:
 
336
          mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
 
337
          break;
 
338
 
 
339
        case GRUB_MEMORY_ACPI:
 
340
          mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
 
341
          break;
 
342
 
 
343
        case GRUB_MEMORY_NVS:
 
344
          mmap_entry->type = MULTIBOOT_MEMORY_NVS;
 
345
          break;
 
346
 
 
347
        case GRUB_MEMORY_BADRAM:
 
348
          mmap_entry->type = MULTIBOOT_MEMORY_BADRAM;
 
349
          break;
 
350
 
 
351
        default:
 
352
          mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
 
353
          break;
 
354
        }
 
355
      mmap_entry++;
 
356
 
 
357
      return 0;
 
358
    }
 
359
 
 
360
  tag->type = MULTIBOOT_TAG_TYPE_MMAP;
 
361
  tag->size = sizeof (struct multiboot_tag_mmap)
 
362
    + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count (); 
 
363
  tag->entry_size = sizeof (struct multiboot_mmap_entry);
 
364
  tag->entry_version = 0;
 
365
 
 
366
  grub_mmap_iterate (hook);
 
367
}
 
368
 
 
369
#if defined (GRUB_MACHINE_PCBIOS)
 
370
static void
 
371
fill_vbe_tag (struct multiboot_tag_vbe *tag)
 
372
{
 
373
  grub_vbe_status_t status;
 
374
  void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
 
375
 
 
376
  tag->type = MULTIBOOT_TAG_TYPE_VBE;
 
377
  tag->size = 0;
 
378
    
 
379
  status = grub_vbe_bios_get_controller_info (scratch);
 
380
  if (status != GRUB_VBE_STATUS_OK)
 
381
    return;
 
382
  
 
383
  grub_memcpy (&tag->vbe_control_info, scratch,
 
384
               sizeof (struct grub_vbe_info_block));
 
385
  
 
386
  status = grub_vbe_bios_get_mode (scratch);
 
387
  tag->vbe_mode = *(grub_uint32_t *) scratch;
 
388
  if (status != GRUB_VBE_STATUS_OK)
 
389
    return;
 
390
 
 
391
  /* get_mode_info isn't available for mode 3.  */
 
392
  if (tag->vbe_mode == 3)
 
393
    {
 
394
      struct grub_vbe_mode_info_block *mode_info = (void *) &tag->vbe_mode_info;
 
395
      grub_memset (mode_info, 0,
 
396
                   sizeof (struct grub_vbe_mode_info_block));
 
397
      mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
 
398
      mode_info->x_resolution = 80;
 
399
      mode_info->y_resolution = 25;
 
400
    }
 
401
  else
 
402
    {
 
403
      status = grub_vbe_bios_get_mode_info (tag->vbe_mode, scratch);
 
404
      if (status != GRUB_VBE_STATUS_OK)
 
405
        return;
 
406
      grub_memcpy (&tag->vbe_mode_info, scratch,
 
407
                   sizeof (struct grub_vbe_mode_info_block));
 
408
    }      
 
409
  grub_vbe_bios_get_pm_interface (&tag->vbe_interface_seg,
 
410
                                  &tag->vbe_interface_off,
 
411
                                  &tag->vbe_interface_len);
 
412
 
 
413
  tag->size = sizeof (*tag);
 
414
}
 
415
#endif
 
416
 
 
417
static grub_err_t
 
418
retrieve_video_parameters (grub_uint8_t **ptrorig)
 
419
{
 
420
  grub_err_t err;
 
421
  struct grub_video_mode_info mode_info;
 
422
  void *framebuffer;
 
423
  grub_video_driver_id_t driv_id;
 
424
  struct grub_video_palette_data palette[256];
 
425
  struct multiboot_tag_framebuffer *tag
 
426
    = (struct multiboot_tag_framebuffer *) *ptrorig;
 
427
 
 
428
  err = grub_multiboot_set_video_mode ();
 
429
  if (err)
 
430
    {
 
431
      grub_print_error ();
 
432
      grub_errno = GRUB_ERR_NONE;
 
433
    }
 
434
 
 
435
  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
 
436
 
 
437
  driv_id = grub_video_get_driver_id ();
 
438
#if HAS_VGA_TEXT
 
439
  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
 
440
    {
 
441
      struct grub_vbe_mode_info_block vbe_mode_info;
 
442
      grub_uint32_t vbe_mode;
 
443
 
 
444
#if defined (GRUB_MACHINE_PCBIOS)
 
445
      {
 
446
        grub_vbe_status_t status;
 
447
        void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
 
448
        status = grub_vbe_bios_get_mode (scratch);
 
449
        vbe_mode = *(grub_uint32_t *) scratch;
 
450
        if (status != GRUB_VBE_STATUS_OK)
 
451
          return GRUB_ERR_NONE;
 
452
      }
 
453
#else
 
454
      vbe_mode = 3;
 
455
#endif
 
456
 
 
457
      /* get_mode_info isn't available for mode 3.  */
 
458
      if (vbe_mode == 3)
 
459
        {
 
460
          grub_memset (&vbe_mode_info, 0,
 
461
                       sizeof (struct grub_vbe_mode_info_block));
 
462
          vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
 
463
          vbe_mode_info.x_resolution = 80;
 
464
          vbe_mode_info.y_resolution = 25;
 
465
        }
 
466
#if defined (GRUB_MACHINE_PCBIOS)
 
467
      else
 
468
        {
 
469
          grub_vbe_status_t status;
 
470
          void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
 
471
          status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
 
472
          if (status != GRUB_VBE_STATUS_OK)
 
473
            return GRUB_ERR_NONE;
 
474
          grub_memcpy (&vbe_mode_info, scratch,
 
475
                       sizeof (struct grub_vbe_mode_info_block));
 
476
        }
 
477
#endif
 
478
 
 
479
      if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
 
480
        {
 
481
          tag = (struct multiboot_tag_framebuffer *) *ptrorig;
 
482
          tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
 
483
          tag->common.size = 0;
 
484
 
 
485
          tag->common.framebuffer_addr = 0xb8000;
 
486
          
 
487
          tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;       
 
488
          tag->common.framebuffer_width = vbe_mode_info.x_resolution;
 
489
          tag->common.framebuffer_height = vbe_mode_info.y_resolution;
 
490
 
 
491
          tag->common.framebuffer_bpp = 16;
 
492
          
 
493
          tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
 
494
          tag->common.size = sizeof (tag->common);
 
495
          tag->common.reserved = 0;
 
496
          *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
 
497
        }
 
498
      return GRUB_ERR_NONE;
 
499
    }
 
500
#else
 
501
  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
 
502
    return GRUB_ERR_NONE;
 
503
#endif
 
504
 
 
505
#if GRUB_MACHINE_HAS_VBE
 
506
  {
 
507
    struct multiboot_tag_vbe *tag_vbe = (struct multiboot_tag_vbe *) *ptrorig;
 
508
 
 
509
    fill_vbe_tag (tag_vbe);
 
510
 
 
511
    *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN);
 
512
  }
 
513
#endif
 
514
 
 
515
  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
 
516
  if (err)
 
517
    return err;
 
518
 
 
519
  tag = (struct multiboot_tag_framebuffer *) *ptrorig;
 
520
  tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
 
521
  tag->common.size = 0;
 
522
 
 
523
  tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
 
524
  tag->common.framebuffer_pitch = mode_info.pitch;
 
525
 
 
526
  tag->common.framebuffer_width = mode_info.width;
 
527
  tag->common.framebuffer_height = mode_info.height;
 
528
 
 
529
  tag->common.framebuffer_bpp = mode_info.bpp;
 
530
 
 
531
  tag->common.reserved = 0;
 
532
      
 
533
  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
 
534
    {
 
535
      unsigned i;
 
536
      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
 
537
      tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
 
538
      if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
 
539
        tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
 
540
      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
 
541
        + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
 
542
        * sizeof (struct multiboot_color);
 
543
      for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
 
544
        {
 
545
          tag->framebuffer_palette[i].red = palette[i].r;
 
546
          tag->framebuffer_palette[i].green = palette[i].g;
 
547
          tag->framebuffer_palette[i].blue = palette[i].b;
 
548
        }
 
549
    }
 
550
  else
 
551
    {
 
552
      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
 
553
      tag->framebuffer_red_field_position = mode_info.red_field_pos;
 
554
      tag->framebuffer_red_mask_size = mode_info.red_mask_size;
 
555
      tag->framebuffer_green_field_position = mode_info.green_field_pos;
 
556
      tag->framebuffer_green_mask_size = mode_info.green_mask_size;
 
557
      tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
 
558
      tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
 
559
 
 
560
      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
 
561
    }
 
562
  *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
 
563
 
 
564
  return GRUB_ERR_NONE;
 
565
}
 
566
 
 
567
grub_err_t
 
568
grub_multiboot_make_mbi (grub_uint32_t *target)
 
569
{
 
570
  grub_uint8_t *ptrorig;
 
571
  grub_uint8_t *mbistart;
 
572
  grub_err_t err;
 
573
  grub_size_t bufsize;
 
574
  grub_relocator_chunk_t ch;
 
575
 
 
576
  bufsize = grub_multiboot_get_mbi_size ();
 
577
 
 
578
  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
 
579
                                          0, 0xffffffff - bufsize,
 
580
                                          bufsize, MULTIBOOT_TAG_ALIGN,
 
581
                                          GRUB_RELOCATOR_PREFERENCE_NONE);
 
582
  if (err)
 
583
    return err;
 
584
 
 
585
  ptrorig = get_virtual_current_address (ch);
 
586
#if defined (__i386__) || defined (__x86_64__)
 
587
  *target = get_physical_target_address (ch);
 
588
#elif defined (__mips)
 
589
  *target = get_physical_target_address (ch) | 0x80000000;
 
590
#else
 
591
#error Please complete this
 
592
#endif
 
593
 
 
594
  mbistart = ptrorig;
 
595
  ptrorig += 2 * sizeof (grub_uint32_t);
 
596
 
 
597
  {
 
598
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
 
599
    tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
 
600
    tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; 
 
601
    grub_memcpy (tag->string, cmdline, cmdline_size);
 
602
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
603
  }
 
604
 
 
605
  {
 
606
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
 
607
    tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
 
608
    tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); 
 
609
    grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
 
610
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
611
  }
 
612
 
 
613
#ifdef GRUB_MACHINE_PCBIOS
 
614
  {
 
615
    struct grub_apm_info info;
 
616
    if (grub_apm_get_info (&info))
 
617
      {
 
618
        struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig;
 
619
 
 
620
        tag->type = MULTIBOOT_TAG_TYPE_APM;
 
621
        tag->size = sizeof (struct multiboot_tag_apm); 
 
622
 
 
623
        tag->cseg = info.cseg;
 
624
        tag->offset = info.offset;
 
625
        tag->cseg_16 = info.cseg_16;
 
626
        tag->dseg = info.dseg;
 
627
        tag->flags = info.flags;
 
628
        tag->cseg_len = info.cseg_len;
 
629
        tag->dseg_len = info.dseg_len;
 
630
        tag->cseg_16_len = info.cseg_16_len;
 
631
        tag->version = info.version;
 
632
 
 
633
        ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
634
      }
 
635
  }
 
636
#endif
 
637
 
 
638
  {
 
639
    unsigned i;
 
640
    struct module *cur;
 
641
 
 
642
    for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
 
643
      {
 
644
        struct multiboot_tag_module *tag
 
645
          = (struct multiboot_tag_module *) ptrorig;
 
646
        tag->type = MULTIBOOT_TAG_TYPE_MODULE;
 
647
        tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
 
648
        tag->mod_start = cur->start;
 
649
        tag->mod_end = tag->mod_start + cur->size;
 
650
        grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
 
651
        ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
652
      }
 
653
  }
 
654
 
 
655
  {
 
656
    struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
 
657
    grub_fill_multiboot_mmap (tag);
 
658
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
659
  }
 
660
 
 
661
  {
 
662
    struct multiboot_tag_elf_sections *tag
 
663
      = (struct multiboot_tag_elf_sections *) ptrorig;
 
664
    tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS;
 
665
    tag->size = sizeof (struct multiboot_tag_elf_sections)
 
666
      + elf_sec_entsize * elf_sec_num;
 
667
    grub_memcpy (tag->sections, elf_sections, elf_sec_entsize * elf_sec_num);
 
668
    tag->num = elf_sec_num;
 
669
    tag->entsize = elf_sec_entsize;
 
670
    tag->shndx = elf_sec_shstrndx;
 
671
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
672
  }
 
673
 
 
674
  {
 
675
    struct multiboot_tag_basic_meminfo *tag
 
676
      = (struct multiboot_tag_basic_meminfo *) ptrorig;
 
677
    tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
 
678
    tag->size = sizeof (struct multiboot_tag_basic_meminfo); 
 
679
 
 
680
    /* Convert from bytes to kilobytes.  */
 
681
    tag->mem_lower = grub_mmap_get_lower () / 1024;
 
682
    tag->mem_upper = grub_mmap_get_upper () / 1024;
 
683
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
684
  }
 
685
 
 
686
  if (bootdev_set)
 
687
    {
 
688
      struct multiboot_tag_bootdev *tag
 
689
        = (struct multiboot_tag_bootdev *) ptrorig;
 
690
      tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
 
691
      tag->size = sizeof (struct multiboot_tag_bootdev); 
 
692
 
 
693
      tag->biosdev = biosdev;
 
694
      tag->slice = slice;
 
695
      tag->part = part;
 
696
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
697
    }
 
698
 
 
699
  {
 
700
    err = retrieve_video_parameters (&ptrorig);
 
701
    if (err)
 
702
      {
 
703
        grub_print_error ();
 
704
        grub_errno = GRUB_ERR_NONE;
 
705
      }
 
706
  }
 
707
 
 
708
#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
 
709
  {
 
710
    struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig;
 
711
    tag->type = MULTIBOOT_TAG_TYPE_EFI64;
 
712
    tag->size = sizeof (*tag);
 
713
    tag->pointer = (grub_addr_t) grub_efi_system_table;
 
714
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
715
  }
 
716
#endif
 
717
 
 
718
#if defined (GRUB_MACHINE_EFI) && defined (__i386__)
 
719
  {
 
720
    struct multiboot_tag_efi32 *tag = (struct multiboot_tag_efi32 *) ptrorig;
 
721
    tag->type = MULTIBOOT_TAG_TYPE_EFI32;
 
722
    tag->size = sizeof (*tag);
 
723
    tag->pointer = (grub_addr_t) grub_efi_system_table;
 
724
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
725
  }
 
726
#endif
 
727
 
 
728
#if GRUB_MACHINE_HAS_ACPI
 
729
  {
 
730
    struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *)
 
731
      ptrorig;
 
732
    struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 ();
 
733
    if (a)
 
734
      {
 
735
        tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
 
736
        tag->size = sizeof (*tag) + sizeof (*a);
 
737
        grub_memcpy (tag->rsdp, a, sizeof (*a));
 
738
        ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
739
      }
 
740
  }
 
741
 
 
742
  {
 
743
    struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *)
 
744
      ptrorig;
 
745
    struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 ();
 
746
    if (a)
 
747
      {
 
748
        tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
 
749
        tag->size = sizeof (*tag) + a->length;
 
750
        grub_memcpy (tag->rsdp, a, a->length);
 
751
        ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
752
      }
 
753
  }
 
754
#endif
 
755
 
 
756
  {
 
757
    struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
 
758
    tag->type = MULTIBOOT_TAG_TYPE_END;
 
759
    tag->size = sizeof (struct multiboot_tag);
 
760
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
 
761
  }
 
762
 
 
763
  ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
 
764
  ((grub_uint32_t *) mbistart)[1] = 0;
 
765
 
 
766
  return GRUB_ERR_NONE;
 
767
}
 
768
 
 
769
void
 
770
grub_multiboot_free_mbi (void)
 
771
{
 
772
  struct module *cur, *next;
 
773
 
 
774
  cmdline_size = 0;
 
775
  total_modcmd = 0;
 
776
  modcnt = 0;
 
777
  grub_free (cmdline);
 
778
  cmdline = NULL;
 
779
  bootdev_set = 0;
 
780
 
 
781
  for (cur = modules; cur; cur = next)
 
782
    {
 
783
      next = cur->next;
 
784
      grub_free (cur->cmdline);
 
785
      grub_free (cur);
 
786
    }
 
787
  modules = NULL;
 
788
  modules_last = NULL;
 
789
}
 
790
 
 
791
grub_err_t
 
792
grub_multiboot_init_mbi (int argc, char *argv[])
 
793
{
 
794
  grub_ssize_t len = 0;
 
795
  char *p;
 
796
  int i;
 
797
 
 
798
  grub_multiboot_free_mbi ();
 
799
 
 
800
  for (i = 0; i < argc; i++)
 
801
    len += grub_strlen (argv[i]) + 1;
 
802
  if (len == 0)
 
803
    len = 1;
 
804
 
 
805
  cmdline = p = grub_malloc (len);
 
806
  if (! cmdline)
 
807
    return grub_errno;
 
808
  cmdline_size = len;
 
809
 
 
810
  for (i = 0; i < argc; i++)
 
811
    {
 
812
      p = grub_stpcpy (p, argv[i]);
 
813
      *(p++) = ' ';
 
814
    }
 
815
 
 
816
  /* Remove the space after the last word.  */
 
817
  if (p != cmdline)
 
818
    p--;
 
819
  *p = '\0';
 
820
 
 
821
  return GRUB_ERR_NONE;
 
822
}
 
823
 
 
824
grub_err_t
 
825
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
 
826
                           int argc, char *argv[])
 
827
{
 
828
  struct module *newmod;
 
829
  char *p;
 
830
  grub_ssize_t len = 0;
 
831
  int i;
 
832
 
 
833
  newmod = grub_malloc (sizeof (*newmod));
 
834
  if (!newmod)
 
835
    return grub_errno;
 
836
  newmod->start = start;
 
837
  newmod->size = size;
 
838
 
 
839
  for (i = 0; i < argc; i++)
 
840
    len += grub_strlen (argv[i]) + 1;
 
841
 
 
842
  if (len == 0)
 
843
    len = 1;
 
844
 
 
845
  newmod->cmdline = p = grub_malloc (len);
 
846
  if (! newmod->cmdline)
 
847
    {
 
848
      grub_free (newmod);
 
849
      return grub_errno;
 
850
    }
 
851
  newmod->cmdline_size = len;
 
852
  total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
 
853
 
 
854
  for (i = 0; i < argc; i++)
 
855
    {
 
856
      p = grub_stpcpy (p, argv[i]);
 
857
      *(p++) = ' ';
 
858
    }
 
859
 
 
860
  /* Remove the space after the last word.  */
 
861
  if (p != newmod->cmdline)
 
862
    p--;
 
863
  *p = '\0';
 
864
 
 
865
  if (modules_last)
 
866
    modules_last->next = newmod;
 
867
  else
 
868
    {
 
869
      modules = newmod;
 
870
      modules_last->next = NULL;
 
871
    }
 
872
  modules_last = newmod;
 
873
 
 
874
  modcnt++;
 
875
 
 
876
  return GRUB_ERR_NONE;
 
877
}
 
878
 
 
879
void
 
880
grub_multiboot_set_bootdev (void)
 
881
{
 
882
  grub_device_t dev;
 
883
 
 
884
  slice = ~0;
 
885
  part = ~0;
 
886
 
 
887
#ifdef GRUB_MACHINE_PCBIOS
 
888
  biosdev = grub_get_root_biosnumber ();
 
889
#else
 
890
  biosdev = 0xffffffff;
 
891
#endif
 
892
 
 
893
  if (biosdev == 0xffffffff)
 
894
    return;
 
895
 
 
896
  dev = grub_device_open (0);
 
897
  if (dev && dev->disk && dev->disk->partition)
 
898
    {
 
899
      if (dev->disk->partition->parent)
 
900
        {
 
901
          part = dev->disk->partition->number;
 
902
          slice = dev->disk->partition->parent->number;
 
903
        }
 
904
      else
 
905
        slice = dev->disk->partition->number;
 
906
    }
 
907
  if (dev)
 
908
    grub_device_close (dev);
 
909
 
 
910
  bootdev_set = 1;
 
911
}