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

« back to all changes in this revision

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