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

« back to all changes in this revision

Viewing changes to 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/machine/memory.h>
20
 
#include <grub/memory.h>
21
 
#ifdef GRUB_MACHINE_PCBIOS
22
 
#include <grub/machine/biosnum.h>
23
 
#endif
24
 
#include <grub/multiboot.h>
25
 
#include <grub/cpu/multiboot.h>
26
 
#include <grub/cpu/relocator.h>
27
 
#include <grub/disk.h>
28
 
#include <grub/device.h>
29
 
#include <grub/partition.h>
30
 
#include <grub/mm.h>
31
 
#include <grub/misc.h>
32
 
#include <grub/env.h>
33
 
#include <grub/video.h>
34
 
 
35
 
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
36
 
#include <grub/i386/pc/vbe.h>
37
 
#define HAS_VGA_TEXT 1
38
 
#else
39
 
#define HAS_VGA_TEXT 0
40
 
#endif
41
 
 
42
 
struct module
43
 
{
44
 
  struct module *next;
45
 
  grub_addr_t start;
46
 
  grub_size_t size;
47
 
  char *cmdline;
48
 
  int cmdline_size;
49
 
};
50
 
 
51
 
struct module *modules, *modules_last;
52
 
static grub_size_t cmdline_size;
53
 
static grub_size_t total_modcmd;
54
 
static unsigned modcnt;
55
 
static char *cmdline = NULL;
56
 
static int bootdev_set;
57
 
static grub_uint32_t biosdev, slice, part;
58
 
 
59
 
grub_err_t
60
 
grub_multiboot_load (grub_file_t file)
61
 
{
62
 
  char *buffer;
63
 
  grub_ssize_t len;
64
 
  struct multiboot_header *header;
65
 
  grub_err_t err;
66
 
  struct multiboot_header_tag *tag;
67
 
  struct multiboot_header_tag_address *addr_tag = NULL;
68
 
  int entry_specified = 0;
69
 
  grub_addr_t entry = 0;
70
 
  grub_uint32_t console_required = 0;
71
 
  struct multiboot_header_tag_framebuffer *fbtag = NULL;
72
 
  int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
73
 
 
74
 
  buffer = grub_malloc (MULTIBOOT_SEARCH);
75
 
  if (!buffer)
76
 
    return grub_errno;
77
 
 
78
 
  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
79
 
  if (len < 32)
80
 
    {
81
 
      grub_free (buffer);
82
 
      return grub_error (GRUB_ERR_BAD_OS, "file too small");
83
 
    }
84
 
 
85
 
  /* Look for the multiboot header in the buffer.  The header should
86
 
     be at least 12 bytes and aligned on a 4-byte boundary.  */
87
 
  for (header = (struct multiboot_header *) buffer;
88
 
       ((char *) header <= buffer + len - 12) || (header = 0);
89
 
       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
90
 
    {
91
 
      if (header->magic == MULTIBOOT_HEADER_MAGIC
92
 
          && !(header->magic + header->architecture
93
 
               + header->header_length + header->checksum)
94
 
          && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
95
 
        break;
96
 
    }
97
 
 
98
 
  if (header == 0)
99
 
    {
100
 
      grub_free (buffer);
101
 
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
102
 
    }
103
 
 
104
 
  for (tag = (struct multiboot_header_tag *) (header + 1);
105
 
       tag->type != MULTIBOOT_TAG_TYPE_END;
106
 
       tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
107
 
    switch (tag->type)
108
 
      {
109
 
      case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
110
 
        {
111
 
          unsigned i;
112
 
          struct multiboot_header_tag_information_request *request_tag
113
 
            = (struct multiboot_header_tag_information_request *) tag;
114
 
          if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
115
 
            break;
116
 
          for (i = 0; i < (request_tag->size - sizeof (request_tag))
117
 
                 / sizeof (request_tag->requests[0]); i++)
118
 
            switch (request_tag->requests[i])
119
 
              {
120
 
              case MULTIBOOT_TAG_TYPE_END:
121
 
              case MULTIBOOT_TAG_TYPE_CMDLINE:
122
 
              case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
123
 
              case MULTIBOOT_TAG_TYPE_MODULE:
124
 
              case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
125
 
              case MULTIBOOT_TAG_TYPE_BOOTDEV:
126
 
              case MULTIBOOT_TAG_TYPE_MMAP:
127
 
              case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
128
 
                break;
129
 
 
130
 
              case MULTIBOOT_TAG_TYPE_VBE:
131
 
              case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
132
 
              case MULTIBOOT_TAG_TYPE_APM:
133
 
              default:
134
 
                grub_free (buffer);
135
 
                return grub_error (GRUB_ERR_UNKNOWN_OS,
136
 
                                   "unsupported information tag: 0x%x",
137
 
                                   request_tag->requests[i]);
138
 
              }
139
 
          break;
140
 
        }
141
 
               
142
 
      case MULTIBOOT_HEADER_TAG_ADDRESS:
143
 
        addr_tag = (struct multiboot_header_tag_address *) tag;
144
 
        break;
145
 
 
146
 
      case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
147
 
        entry_specified = 1;
148
 
        entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
149
 
        break;
150
 
 
151
 
      case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
152
 
        if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
153
 
            & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
154
 
          accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
155
 
        if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
156
 
            & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
157
 
          console_required = 1;
158
 
        break;
159
 
 
160
 
      case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
161
 
        fbtag = (struct multiboot_header_tag_framebuffer *) tag;
162
 
        accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
163
 
        break;
164
 
 
165
 
        /* GRUB always page-aligns modules.  */
166
 
      case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
167
 
        break;
168
 
 
169
 
      default:
170
 
        if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
171
 
          {
172
 
            grub_free (buffer);
173
 
            return grub_error (GRUB_ERR_UNKNOWN_OS,
174
 
                               "unsupported tag: 0x%x", tag->type);
175
 
          }
176
 
        break;
177
 
      }
178
 
 
179
 
  if (addr_tag && !entry_specified)
180
 
    {
181
 
      grub_free (buffer);
182
 
      return grub_error (GRUB_ERR_UNKNOWN_OS,
183
 
                         "load address tag without entry address tag");
184
 
    }
185
 
 
186
 
  if (addr_tag)
187
 
    {
188
 
      int offset = ((char *) header - buffer -
189
 
                    (addr_tag->header_addr - addr_tag->load_addr));
190
 
      int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
191
 
                       addr_tag->load_end_addr - addr_tag->load_addr);
192
 
      grub_size_t code_size;
193
 
 
194
 
      if (addr_tag->bss_end_addr)
195
 
        code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
196
 
      else
197
 
        code_size = load_size;
198
 
      grub_multiboot_payload_dest = addr_tag->load_addr;
199
 
 
200
 
      grub_multiboot_pure_size += code_size;
201
 
 
202
 
      /* Allocate a bit more to avoid relocations in most cases.  */
203
 
      grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
204
 
      grub_multiboot_payload_orig
205
 
        = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
206
 
 
207
 
      if (! grub_multiboot_payload_orig)
208
 
        {
209
 
          grub_free (buffer);
210
 
          return grub_errno;
211
 
        }
212
 
 
213
 
      if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
214
 
        {
215
 
          grub_free (buffer);
216
 
          return grub_errno;
217
 
        }
218
 
 
219
 
      grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
220
 
      if (grub_errno)
221
 
        {
222
 
          grub_free (buffer);
223
 
          return grub_errno;
224
 
        }
225
 
 
226
 
      if (addr_tag->bss_end_addr)
227
 
        grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
228
 
                     addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
229
 
    }
230
 
  else
231
 
    {
232
 
      err = grub_multiboot_load_elf (file, buffer);
233
 
      if (err)
234
 
        {
235
 
          grub_free (buffer);
236
 
          return err;
237
 
        }
238
 
    }
239
 
 
240
 
  if (entry_specified)
241
 
    grub_multiboot_payload_eip = entry;
242
 
 
243
 
  if (fbtag)
244
 
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
245
 
                                      accepted_consoles,
246
 
                                      fbtag->width, fbtag->height,
247
 
                                      fbtag->depth, console_required);
248
 
  else
249
 
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
250
 
                                      accepted_consoles,
251
 
                                      0, 0, 0, console_required);
252
 
  return err;
253
 
}
254
 
 
255
 
grub_size_t
256
 
grub_multiboot_get_mbi_size (void)
257
 
{
258
 
  return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
259
 
    + (sizeof (struct multiboot_tag_string)
260
 
       + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
261
 
    + (sizeof (struct multiboot_tag_string)
262
 
       + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
263
 
    + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
264
 
    + sizeof (struct multiboot_tag_basic_meminfo)
265
 
    + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
266
 
    + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
267
 
       * sizeof (struct multiboot_mmap_entry))
268
 
    + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
269
 
}
270
 
 
271
 
/* Fill previously allocated Multiboot mmap.  */
272
 
static void
273
 
grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
274
 
{
275
 
  struct multiboot_mmap_entry *mmap_entry = tag->entries;
276
 
 
277
 
  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
278
 
  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
279
 
    {
280
 
      mmap_entry->addr = addr;
281
 
      mmap_entry->len = size;
282
 
      switch (type)
283
 
        {
284
 
        case GRUB_MACHINE_MEMORY_AVAILABLE:
285
 
          mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
286
 
          break;
287
 
 
288
 
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
289
 
        case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
290
 
          mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
291
 
          break;
292
 
#endif
293
 
 
294
 
#ifdef GRUB_MACHINE_MEMORY_NVS
295
 
        case GRUB_MACHINE_MEMORY_NVS:
296
 
          mmap_entry->type = MULTIBOOT_MEMORY_NVS;
297
 
          break;
298
 
#endif    
299
 
          
300
 
        default:
301
 
          mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
302
 
          break;
303
 
        }
304
 
      mmap_entry++;
305
 
 
306
 
      return 0;
307
 
    }
308
 
 
309
 
  tag->type = MULTIBOOT_TAG_TYPE_MMAP;
310
 
  tag->size = sizeof (struct multiboot_tag_mmap)
311
 
    + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count (); 
312
 
  tag->entry_size = sizeof (struct multiboot_mmap_entry);
313
 
  tag->entry_version = 0;
314
 
 
315
 
  grub_mmap_iterate (hook);
316
 
}
317
 
 
318
 
static grub_err_t
319
 
retrieve_video_parameters (grub_uint8_t **ptrorig)
320
 
{
321
 
  grub_err_t err;
322
 
  struct grub_video_mode_info mode_info;
323
 
  void *framebuffer;
324
 
  grub_video_driver_id_t driv_id;
325
 
  struct grub_video_palette_data palette[256];
326
 
  struct multiboot_tag_framebuffer *tag
327
 
    = (struct multiboot_tag_framebuffer *) *ptrorig;
328
 
 
329
 
  err = grub_multiboot_set_video_mode ();
330
 
  if (err)
331
 
    {
332
 
      grub_print_error ();
333
 
      grub_errno = GRUB_ERR_NONE;
334
 
    }
335
 
 
336
 
  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
337
 
 
338
 
  driv_id = grub_video_get_driver_id ();
339
 
#if HAS_VGA_TEXT
340
 
  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
341
 
    {
342
 
      struct grub_vbe_mode_info_block vbe_mode_info;
343
 
      grub_uint32_t vbe_mode;
344
 
 
345
 
#if defined (GRUB_MACHINE_PCBIOS)
346
 
      {
347
 
        grub_vbe_status_t status;
348
 
        void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
349
 
        status = grub_vbe_bios_get_mode (scratch);
350
 
        vbe_mode = *(grub_uint32_t *) scratch;
351
 
        if (status != GRUB_VBE_STATUS_OK)
352
 
          return GRUB_ERR_NONE;
353
 
      }
354
 
#else
355
 
      vbe_mode = 3;
356
 
#endif
357
 
 
358
 
      /* get_mode_info isn't available for mode 3.  */
359
 
      if (vbe_mode == 3)
360
 
        {
361
 
          grub_memset (&vbe_mode_info, 0,
362
 
                       sizeof (struct grub_vbe_mode_info_block));
363
 
          vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
364
 
          vbe_mode_info.x_resolution = 80;
365
 
          vbe_mode_info.y_resolution = 25;
366
 
        }
367
 
#if defined (GRUB_MACHINE_PCBIOS)
368
 
      else
369
 
        {
370
 
          grub_vbe_status_t status;
371
 
          void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
372
 
          status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
373
 
          if (status != GRUB_VBE_STATUS_OK)
374
 
            return GRUB_ERR_NONE;
375
 
          grub_memcpy (&vbe_mode_info, scratch,
376
 
                       sizeof (struct grub_vbe_mode_info_block));
377
 
        }
378
 
#endif
379
 
 
380
 
      if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
381
 
        {
382
 
          tag = (struct multiboot_tag_framebuffer *) *ptrorig;
383
 
          tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
384
 
          tag->common.size = 0;
385
 
 
386
 
          tag->common.framebuffer_addr = 0xb8000;
387
 
          
388
 
          tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;       
389
 
          tag->common.framebuffer_width = vbe_mode_info.x_resolution;
390
 
          tag->common.framebuffer_height = vbe_mode_info.y_resolution;
391
 
 
392
 
          tag->common.framebuffer_bpp = 16;
393
 
          
394
 
          tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
395
 
          tag->common.size = sizeof (tag->common);
396
 
          tag->common.reserved = 0;
397
 
          *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
398
 
        }
399
 
      return GRUB_ERR_NONE;
400
 
    }
401
 
#else
402
 
  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
403
 
    return GRUB_ERR_NONE;
404
 
#endif
405
 
 
406
 
  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
407
 
  if (err)
408
 
    return err;
409
 
 
410
 
  tag = (struct multiboot_tag_framebuffer *) *ptrorig;
411
 
  tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
412
 
  tag->common.size = 0;
413
 
 
414
 
  tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
415
 
  tag->common.framebuffer_pitch = mode_info.pitch;
416
 
 
417
 
  tag->common.framebuffer_width = mode_info.width;
418
 
  tag->common.framebuffer_height = mode_info.height;
419
 
 
420
 
  tag->common.framebuffer_bpp = mode_info.bpp;
421
 
 
422
 
  tag->common.reserved = 0;
423
 
      
424
 
  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
425
 
    {
426
 
      unsigned i;
427
 
      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
428
 
      tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
429
 
      if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
430
 
        tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
431
 
      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
432
 
        + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
433
 
        * sizeof (struct multiboot_color);
434
 
      for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
435
 
        {
436
 
          tag->framebuffer_palette[i].red = palette[i].r;
437
 
          tag->framebuffer_palette[i].green = palette[i].g;
438
 
          tag->framebuffer_palette[i].blue = palette[i].b;
439
 
        }
440
 
    }
441
 
  else
442
 
    {
443
 
      tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
444
 
      tag->framebuffer_red_field_position = mode_info.red_field_pos;
445
 
      tag->framebuffer_red_mask_size = mode_info.red_mask_size;
446
 
      tag->framebuffer_green_field_position = mode_info.green_field_pos;
447
 
      tag->framebuffer_green_mask_size = mode_info.green_mask_size;
448
 
      tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
449
 
      tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
450
 
 
451
 
      tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
452
 
    }
453
 
  *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
454
 
 
455
 
  return GRUB_ERR_NONE;
456
 
}
457
 
 
458
 
grub_err_t
459
 
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
460
 
                         grub_size_t bufsize)
461
 
{
462
 
  grub_uint8_t *ptrorig;
463
 
  grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off 
464
 
    + (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off));
465
 
  grub_err_t err;
466
 
 
467
 
  if (bufsize < grub_multiboot_get_mbi_size ())
468
 
    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
469
 
 
470
 
  ptrorig = mbistart + 2 * sizeof (grub_uint32_t);
471
 
 
472
 
  {
473
 
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
474
 
    tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
475
 
    tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; 
476
 
    grub_memcpy (tag->string, cmdline, cmdline_size);
477
 
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
478
 
  }
479
 
 
480
 
  {
481
 
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
482
 
    tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
483
 
    tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); 
484
 
    grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
485
 
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
486
 
  }
487
 
 
488
 
  {
489
 
    unsigned i;
490
 
    struct module *cur;
491
 
 
492
 
    for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
493
 
      {
494
 
        struct multiboot_tag_module *tag
495
 
          = (struct multiboot_tag_module *) ptrorig;
496
 
        tag->type = MULTIBOOT_TAG_TYPE_MODULE;
497
 
        tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
498
 
        tag->mod_start = cur->start;
499
 
        tag->mod_end = tag->mod_start + cur->size;
500
 
        grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
501
 
        ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
502
 
      }
503
 
  }
504
 
 
505
 
  {
506
 
    struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
507
 
    grub_fill_multiboot_mmap (tag);
508
 
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
509
 
  }
510
 
 
511
 
  {
512
 
    struct multiboot_tag_basic_meminfo *tag
513
 
      = (struct multiboot_tag_basic_meminfo *) ptrorig;
514
 
    tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
515
 
    tag->size = sizeof (struct multiboot_tag_basic_meminfo); 
516
 
 
517
 
    /* Convert from bytes to kilobytes.  */
518
 
    tag->mem_lower = grub_mmap_get_lower () / 1024;
519
 
    tag->mem_upper = grub_mmap_get_upper () / 1024;
520
 
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
521
 
  }
522
 
 
523
 
  if (bootdev_set)
524
 
    {
525
 
      struct multiboot_tag_bootdev *tag
526
 
        = (struct multiboot_tag_bootdev *) ptrorig;
527
 
      tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
528
 
      tag->size = sizeof (struct multiboot_tag_bootdev); 
529
 
 
530
 
      tag->biosdev = biosdev;
531
 
      tag->slice = slice;
532
 
      tag->part = part;
533
 
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
534
 
    }
535
 
 
536
 
  {
537
 
    err = retrieve_video_parameters (&ptrorig);
538
 
    if (err)
539
 
      {
540
 
        grub_print_error ();
541
 
        grub_errno = GRUB_ERR_NONE;
542
 
      }
543
 
  }
544
 
  
545
 
  {
546
 
    struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
547
 
    tag->type = MULTIBOOT_TAG_TYPE_END;
548
 
    tag->size = sizeof (struct multiboot_tag);
549
 
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
550
 
  }
551
 
 
552
 
  ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
553
 
  ((grub_uint32_t *) mbistart)[1] = 0;
554
 
 
555
 
  return GRUB_ERR_NONE;
556
 
}
557
 
 
558
 
void
559
 
grub_multiboot_free_mbi (void)
560
 
{
561
 
  struct module *cur, *next;
562
 
 
563
 
  cmdline_size = 0;
564
 
  total_modcmd = 0;
565
 
  modcnt = 0;
566
 
  grub_free (cmdline);
567
 
  cmdline = NULL;
568
 
  bootdev_set = 0;
569
 
 
570
 
  for (cur = modules; cur; cur = next)
571
 
    {
572
 
      next = cur->next;
573
 
      grub_free (cur->cmdline);
574
 
      grub_free (cur);
575
 
    }
576
 
  modules = NULL;
577
 
  modules_last = NULL;
578
 
}
579
 
 
580
 
grub_err_t
581
 
grub_multiboot_init_mbi (int argc, char *argv[])
582
 
{
583
 
  grub_ssize_t len = 0;
584
 
  char *p;
585
 
  int i;
586
 
 
587
 
  grub_multiboot_free_mbi ();
588
 
 
589
 
  for (i = 0; i < argc; i++)
590
 
    len += grub_strlen (argv[i]) + 1;
591
 
  if (len == 0)
592
 
    len = 1;
593
 
 
594
 
  cmdline = p = grub_malloc (len);
595
 
  if (! cmdline)
596
 
    return grub_errno;
597
 
  cmdline_size = len;
598
 
 
599
 
  for (i = 0; i < argc; i++)
600
 
    {
601
 
      p = grub_stpcpy (p, argv[i]);
602
 
      *(p++) = ' ';
603
 
    }
604
 
 
605
 
  /* Remove the space after the last word.  */
606
 
  if (p != cmdline)
607
 
    p--;
608
 
  *p = '\0';
609
 
 
610
 
  return GRUB_ERR_NONE;
611
 
}
612
 
 
613
 
grub_err_t
614
 
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
615
 
                           int argc, char *argv[])
616
 
{
617
 
  struct module *newmod;
618
 
  char *p;
619
 
  grub_ssize_t len = 0;
620
 
  int i;
621
 
 
622
 
  newmod = grub_malloc (sizeof (*newmod));
623
 
  if (!newmod)
624
 
    return grub_errno;
625
 
  newmod->start = start;
626
 
  newmod->size = size;
627
 
 
628
 
  for (i = 0; i < argc; i++)
629
 
    len += grub_strlen (argv[i]) + 1;
630
 
 
631
 
  if (len == 0)
632
 
    len = 1;
633
 
 
634
 
  newmod->cmdline = p = grub_malloc (len);
635
 
  if (! newmod->cmdline)
636
 
    {
637
 
      grub_free (newmod);
638
 
      return grub_errno;
639
 
    }
640
 
  newmod->cmdline_size = len;
641
 
  total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
642
 
 
643
 
  for (i = 0; i < argc; i++)
644
 
    {
645
 
      p = grub_stpcpy (p, argv[i]);
646
 
      *(p++) = ' ';
647
 
    }
648
 
 
649
 
  /* Remove the space after the last word.  */
650
 
  if (p != newmod->cmdline)
651
 
    p--;
652
 
  *p = '\0';
653
 
 
654
 
  if (modules_last)
655
 
    modules_last->next = newmod;
656
 
  else
657
 
    {
658
 
      modules = newmod;
659
 
      modules_last->next = NULL;
660
 
    }
661
 
  modules_last = newmod;
662
 
 
663
 
  modcnt++;
664
 
 
665
 
  return GRUB_ERR_NONE;
666
 
}
667
 
 
668
 
void
669
 
grub_multiboot_set_bootdev (void)
670
 
{
671
 
  grub_device_t dev;
672
 
 
673
 
  slice = ~0;
674
 
  part = ~0;
675
 
 
676
 
#ifdef GRUB_MACHINE_PCBIOS
677
 
  biosdev = grub_get_root_biosnumber ();
678
 
#else
679
 
  biosdev = 0xffffffff;
680
 
#endif
681
 
 
682
 
  if (biosdev == 0xffffffff)
683
 
    return;
684
 
 
685
 
  dev = grub_device_open (0);
686
 
  if (dev && dev->disk && dev->disk->partition)
687
 
    {
688
 
      if (dev->disk->partition->parent)
689
 
        {
690
 
          part = dev->disk->partition->number;
691
 
          slice = dev->disk->partition->parent->number;
692
 
        }
693
 
      else
694
 
        slice = dev->disk->partition->number;
695
 
    }
696
 
  if (dev)
697
 
    grub_device_close (dev);
698
 
 
699
 
  bootdev_set = 1;
700
 
}