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

« back to all changes in this revision

Viewing changes to 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/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
 
#include <grub/file.h>
35
 
 
36
 
/* The bits in the required part of flags field we don't support.  */
37
 
#define UNSUPPORTED_FLAGS                       0x0000fff8
38
 
 
39
 
struct module
40
 
{
41
 
  struct module *next;
42
 
  grub_addr_t start;
43
 
  grub_size_t size;
44
 
  char *cmdline;
45
 
  int cmdline_size;
46
 
};
47
 
 
48
 
struct module *modules, *modules_last;
49
 
static grub_size_t cmdline_size;
50
 
static grub_size_t total_modcmd;
51
 
static unsigned modcnt;
52
 
static char *cmdline = NULL;
53
 
static grub_uint32_t bootdev;
54
 
static int bootdev_set;
55
 
 
56
 
grub_err_t
57
 
grub_multiboot_load (grub_file_t file)
58
 
{
59
 
  char *buffer;
60
 
  grub_ssize_t len;
61
 
  struct multiboot_header *header;
62
 
  grub_err_t err;
63
 
 
64
 
  buffer = grub_malloc (MULTIBOOT_SEARCH);
65
 
  if (!buffer)
66
 
    return grub_errno;
67
 
 
68
 
  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
69
 
  if (len < 32)
70
 
    {
71
 
      grub_free (buffer);
72
 
      return grub_error (GRUB_ERR_BAD_OS, "file too small");
73
 
    }
74
 
 
75
 
  /* Look for the multiboot header in the buffer.  The header should
76
 
     be at least 12 bytes and aligned on a 4-byte boundary.  */
77
 
  for (header = (struct multiboot_header *) buffer;
78
 
       ((char *) header <= buffer + len - 12) || (header = 0);
79
 
       header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
80
 
    {
81
 
      if (header->magic == MULTIBOOT_HEADER_MAGIC
82
 
          && !(header->magic + header->flags + header->checksum))
83
 
        break;
84
 
    }
85
 
 
86
 
  if (header == 0)
87
 
    {
88
 
      grub_free (buffer);
89
 
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
90
 
    }
91
 
 
92
 
  if (header->flags & UNSUPPORTED_FLAGS)
93
 
    {
94
 
      grub_free (buffer);
95
 
      return grub_error (GRUB_ERR_UNKNOWN_OS,
96
 
                         "unsupported flag: 0x%x", header->flags);
97
 
    }
98
 
 
99
 
  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
100
 
    {
101
 
      int offset = ((char *) header - buffer -
102
 
                    (header->header_addr - header->load_addr));
103
 
      int load_size = ((header->load_end_addr == 0) ? file->size - offset :
104
 
                       header->load_end_addr - header->load_addr);
105
 
      grub_size_t code_size;
106
 
 
107
 
      if (header->bss_end_addr)
108
 
        code_size = (header->bss_end_addr - header->load_addr);
109
 
      else
110
 
        code_size = load_size;
111
 
      grub_multiboot_payload_dest = header->load_addr;
112
 
 
113
 
      grub_multiboot_pure_size += code_size;
114
 
 
115
 
      /* Allocate a bit more to avoid relocations in most cases.  */
116
 
      grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
117
 
      grub_multiboot_payload_orig
118
 
        = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
119
 
 
120
 
      if (! grub_multiboot_payload_orig)
121
 
        {
122
 
          grub_free (buffer);
123
 
          return grub_errno;
124
 
        }
125
 
 
126
 
      if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
127
 
        {
128
 
          grub_free (buffer);
129
 
          return grub_errno;
130
 
        }
131
 
 
132
 
      grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
133
 
      if (grub_errno)
134
 
        {
135
 
          grub_free (buffer);
136
 
          return grub_errno;
137
 
        }
138
 
 
139
 
      if (header->bss_end_addr)
140
 
        grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
141
 
                     header->bss_end_addr - header->load_addr - load_size);
142
 
 
143
 
      grub_multiboot_payload_eip = header->entry_addr;
144
 
 
145
 
    }
146
 
  else
147
 
    {
148
 
      err = grub_multiboot_load_elf (file, buffer);
149
 
      if (err)
150
 
        {
151
 
          grub_free (buffer);
152
 
          return err;
153
 
        }
154
 
    }
155
 
 
156
 
  if (header->flags & MULTIBOOT_VIDEO_MODE)
157
 
    {
158
 
      switch (header->mode_type)
159
 
        {
160
 
        case 1:
161
 
          err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT, 
162
 
                                            GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
163
 
                                            | GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
164
 
                                            0, 0, 0, 0);
165
 
          break;
166
 
        case 0:
167
 
          err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
168
 
                                            GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
169
 
                                            | GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
170
 
                                            header->width, header->height,
171
 
                                            header->depth, 0);
172
 
          break;
173
 
        default:
174
 
          err = grub_error (GRUB_ERR_BAD_OS, 
175
 
                            "unsupported graphical mode type %d",
176
 
                            header->mode_type);
177
 
          break;
178
 
        }
179
 
    }
180
 
  else
181
 
    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT, 
182
 
                                      GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
183
 
                                      0, 0, 0, 0);
184
 
  return err;
185
 
}
186
 
 
187
 
grub_size_t
188
 
grub_multiboot_get_mbi_size (void)
189
 
{
190
 
  return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
191
 
    + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
192
 
    + ALIGN_UP (sizeof(PACKAGE_STRING), 4) 
193
 
    + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
194
 
    + 256 * sizeof (struct multiboot_color);
195
 
}
196
 
 
197
 
/* Fill previously allocated Multiboot mmap.  */
198
 
static void
199
 
grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
200
 
{
201
 
  struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry;
202
 
 
203
 
  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
204
 
  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
205
 
    {
206
 
      mmap_entry->addr = addr;
207
 
      mmap_entry->len = size;
208
 
      switch (type)
209
 
        {
210
 
        case GRUB_MACHINE_MEMORY_AVAILABLE:
211
 
          mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
212
 
          break;
213
 
 
214
 
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
215
 
        case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
216
 
          mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
217
 
          break;
218
 
#endif
219
 
 
220
 
#ifdef GRUB_MACHINE_MEMORY_NVS
221
 
        case GRUB_MACHINE_MEMORY_NVS:
222
 
          mmap_entry->type = MULTIBOOT_MEMORY_NVS;
223
 
          break;
224
 
#endif    
225
 
          
226
 
        default:
227
 
          mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
228
 
          break;
229
 
        }
230
 
      mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size);
231
 
      mmap_entry++;
232
 
 
233
 
      return 0;
234
 
    }
235
 
 
236
 
  grub_mmap_iterate (hook);
237
 
}
238
 
 
239
 
static grub_err_t
240
 
retrieve_video_parameters (struct multiboot_info *mbi,
241
 
                           grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
242
 
{
243
 
  grub_err_t err;
244
 
  struct grub_video_mode_info mode_info;
245
 
  void *framebuffer;
246
 
  grub_video_driver_id_t driv_id;
247
 
  struct grub_video_palette_data palette[256];
248
 
 
249
 
  err = grub_multiboot_set_video_mode ();
250
 
  if (err)
251
 
    {
252
 
      grub_print_error ();
253
 
      grub_errno = GRUB_ERR_NONE;
254
 
    }
255
 
 
256
 
  grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
257
 
 
258
 
  driv_id = grub_video_get_driver_id ();
259
 
  if (driv_id == GRUB_VIDEO_DRIVER_NONE)
260
 
    return GRUB_ERR_NONE;
261
 
 
262
 
  err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
263
 
  if (err)
264
 
    return err;
265
 
 
266
 
  mbi->framebuffer_addr = (grub_addr_t) framebuffer;
267
 
  mbi->framebuffer_pitch = mode_info.pitch;
268
 
 
269
 
  mbi->framebuffer_width = mode_info.width;
270
 
  mbi->framebuffer_height = mode_info.height;
271
 
 
272
 
  mbi->framebuffer_bpp = mode_info.bpp;
273
 
      
274
 
  if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
275
 
    {
276
 
      struct multiboot_color *mb_palette;
277
 
      unsigned i;
278
 
      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
279
 
      mbi->framebuffer_palette_addr = ptrdest;
280
 
      mbi->framebuffer_palette_num_colors = mode_info.number_of_colors;
281
 
      if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
282
 
        mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
283
 
      mb_palette = (struct multiboot_color *) ptrorig;
284
 
      for (i = 0; i < mbi->framebuffer_palette_num_colors; i++)
285
 
        {
286
 
          mb_palette[i].red = palette[i].r;
287
 
          mb_palette[i].green = palette[i].g;
288
 
          mb_palette[i].blue = palette[i].b;
289
 
        }
290
 
      ptrorig += mbi->framebuffer_palette_num_colors
291
 
        * sizeof (struct multiboot_color);
292
 
      ptrdest += mbi->framebuffer_palette_num_colors
293
 
        * sizeof (struct multiboot_color);
294
 
    }
295
 
  else
296
 
    {
297
 
      mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
298
 
      mbi->framebuffer_red_field_position = mode_info.red_field_pos;
299
 
      mbi->framebuffer_red_mask_size = mode_info.red_mask_size;
300
 
      mbi->framebuffer_green_field_position = mode_info.green_field_pos;
301
 
      mbi->framebuffer_green_mask_size = mode_info.green_mask_size;
302
 
      mbi->framebuffer_blue_field_position = mode_info.blue_field_pos;
303
 
      mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size;
304
 
    }
305
 
 
306
 
  mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO;
307
 
 
308
 
  return GRUB_ERR_NONE;
309
 
}
310
 
 
311
 
grub_err_t
312
 
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
313
 
                         grub_size_t bufsize)
314
 
{
315
 
  grub_uint8_t *ptrorig = (grub_uint8_t *) orig + buf_off;
316
 
  grub_uint32_t ptrdest = dest + buf_off;
317
 
  struct multiboot_info *mbi;
318
 
  struct multiboot_mod_list *modlist;
319
 
  unsigned i;
320
 
  struct module *cur;
321
 
  grub_size_t mmap_size;
322
 
  grub_err_t err;
323
 
 
324
 
  if (bufsize < grub_multiboot_get_mbi_size ())
325
 
    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
326
 
 
327
 
  mbi = (struct multiboot_info *) ptrorig;
328
 
  ptrorig += sizeof (*mbi);
329
 
  ptrdest += sizeof (*mbi);
330
 
  grub_memset (mbi, 0, sizeof (*mbi));
331
 
 
332
 
  grub_memcpy (ptrorig, cmdline, cmdline_size);
333
 
  mbi->flags |= MULTIBOOT_INFO_CMDLINE;
334
 
  mbi->cmdline = ptrdest;
335
 
  ptrorig += ALIGN_UP (cmdline_size, 4);
336
 
  ptrdest += ALIGN_UP (cmdline_size, 4);
337
 
 
338
 
  grub_memcpy (ptrorig, PACKAGE_STRING, sizeof(PACKAGE_STRING));
339
 
  mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
340
 
  mbi->boot_loader_name = ptrdest;
341
 
  ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
342
 
  ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4);
343
 
 
344
 
  if (modcnt)
345
 
    {
346
 
      mbi->flags |= MULTIBOOT_INFO_MODS;
347
 
      mbi->mods_addr = ptrdest;
348
 
      mbi->mods_count = modcnt;
349
 
      modlist = (struct multiboot_mod_list *) ptrorig;
350
 
      ptrorig += modcnt * sizeof (struct multiboot_mod_list);
351
 
      ptrdest += modcnt * sizeof (struct multiboot_mod_list);
352
 
 
353
 
      for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
354
 
        {
355
 
          modlist[i].mod_start = cur->start;
356
 
          modlist[i].mod_end = modlist[i].mod_start + cur->size;
357
 
          modlist[i].cmdline = ptrdest;
358
 
          grub_memcpy (ptrorig, cur->cmdline, cur->cmdline_size);
359
 
          ptrorig += ALIGN_UP (cur->cmdline_size, 4);
360
 
          ptrdest += ALIGN_UP (cur->cmdline_size, 4);
361
 
        }
362
 
    }
363
 
  else
364
 
    {
365
 
      mbi->mods_addr = 0;
366
 
      mbi->mods_count = 0;
367
 
    }
368
 
 
369
 
  mmap_size = grub_get_multiboot_mmap_count () 
370
 
    * sizeof (struct multiboot_mmap_entry);
371
 
  grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
372
 
  mbi->mmap_length = mmap_size;
373
 
  mbi->mmap_addr = ptrdest;
374
 
  mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
375
 
  ptrorig += mmap_size;
376
 
  ptrdest += mmap_size;
377
 
 
378
 
  /* Convert from bytes to kilobytes.  */
379
 
  mbi->mem_lower = grub_mmap_get_lower () / 1024;
380
 
  mbi->mem_upper = grub_mmap_get_upper () / 1024;
381
 
  mbi->flags |= MULTIBOOT_INFO_MEMORY;
382
 
 
383
 
  if (bootdev_set)
384
 
    {
385
 
      mbi->boot_device = bootdev;
386
 
      mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
387
 
    }
388
 
 
389
 
  err = retrieve_video_parameters (mbi, ptrorig, ptrdest);
390
 
  if (err)
391
 
    {
392
 
      grub_print_error ();
393
 
      grub_errno = GRUB_ERR_NONE;
394
 
    }
395
 
 
396
 
  return GRUB_ERR_NONE;
397
 
}
398
 
 
399
 
void
400
 
grub_multiboot_free_mbi (void)
401
 
{
402
 
  struct module *cur, *next;
403
 
 
404
 
  cmdline_size = 0;
405
 
  total_modcmd = 0;
406
 
  modcnt = 0;
407
 
  grub_free (cmdline);
408
 
  cmdline = NULL;
409
 
  bootdev_set = 0;
410
 
 
411
 
  for (cur = modules; cur; cur = next)
412
 
    {
413
 
      next = cur->next;
414
 
      grub_free (cur->cmdline);
415
 
      grub_free (cur);
416
 
    }
417
 
  modules = NULL;
418
 
  modules_last = NULL;
419
 
}
420
 
 
421
 
grub_err_t
422
 
grub_multiboot_init_mbi (int argc, char *argv[])
423
 
{
424
 
  grub_ssize_t len = 0;
425
 
  char *p;
426
 
  int i;
427
 
 
428
 
  grub_multiboot_free_mbi ();
429
 
 
430
 
  for (i = 0; i < argc; i++)
431
 
    len += grub_strlen (argv[i]) + 1;
432
 
  if (len == 0)
433
 
    len = 1;
434
 
 
435
 
  cmdline = p = grub_malloc (len);
436
 
  if (! cmdline)
437
 
    return grub_errno;
438
 
  cmdline_size = len;
439
 
 
440
 
  for (i = 0; i < argc; i++)
441
 
    {
442
 
      p = grub_stpcpy (p, argv[i]);
443
 
      *(p++) = ' ';
444
 
    }
445
 
 
446
 
  /* Remove the space after the last word.  */
447
 
  if (p != cmdline)
448
 
    p--;
449
 
  *p = '\0';
450
 
 
451
 
  return GRUB_ERR_NONE;
452
 
}
453
 
 
454
 
grub_err_t
455
 
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
456
 
                           int argc, char *argv[])
457
 
{
458
 
  struct module *newmod;
459
 
  char *p;
460
 
  grub_ssize_t len = 0;
461
 
  int i;
462
 
 
463
 
  newmod = grub_malloc (sizeof (*newmod));
464
 
  if (!newmod)
465
 
    return grub_errno;
466
 
  newmod->start = start;
467
 
  newmod->size = size;
468
 
 
469
 
  for (i = 0; i < argc; i++)
470
 
    len += grub_strlen (argv[i]) + 1;
471
 
 
472
 
  if (len == 0)
473
 
    len = 1;
474
 
 
475
 
  newmod->cmdline = p = grub_malloc (len);
476
 
  if (! newmod->cmdline)
477
 
    {
478
 
      grub_free (newmod);
479
 
      return grub_errno;
480
 
    }
481
 
  newmod->cmdline_size = len;
482
 
  total_modcmd += ALIGN_UP (len, 4);
483
 
 
484
 
  for (i = 0; i < argc; i++)
485
 
    {
486
 
      p = grub_stpcpy (p, argv[i]);
487
 
      *(p++) = ' ';
488
 
    }
489
 
 
490
 
  /* Remove the space after the last word.  */
491
 
  if (p != newmod->cmdline)
492
 
    p--;
493
 
  *p = '\0';
494
 
 
495
 
  if (modules_last)
496
 
    modules_last->next = newmod;
497
 
  else
498
 
    {
499
 
      modules = newmod;
500
 
      modules_last->next = NULL;
501
 
    }
502
 
  modules_last = newmod;
503
 
 
504
 
  modcnt++;
505
 
 
506
 
  return GRUB_ERR_NONE;
507
 
}
508
 
 
509
 
void
510
 
grub_multiboot_set_bootdev (void)
511
 
{
512
 
  grub_uint32_t biosdev, slice = ~0, part = ~0;
513
 
  grub_device_t dev;
514
 
 
515
 
#ifdef GRUB_MACHINE_PCBIOS
516
 
  biosdev = grub_get_root_biosnumber ();
517
 
#else
518
 
  biosdev = 0xffffffff;
519
 
#endif
520
 
 
521
 
  if (biosdev == 0xffffffff)
522
 
    return;
523
 
 
524
 
  dev = grub_device_open (0);
525
 
  if (dev && dev->disk && dev->disk->partition)
526
 
    {
527
 
      if (dev->disk->partition->parent)
528
 
        {
529
 
          part = dev->disk->partition->number;
530
 
          slice = dev->disk->partition->parent->number;
531
 
        }
532
 
      else
533
 
        slice = dev->disk->partition->number;
534
 
    }
535
 
  if (dev)
536
 
    grub_device_close (dev);
537
 
 
538
 
  bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16) 
539
 
    | ((part & 0xff) << 8) | 0xff;
540
 
  bootdev_set = 1;
541
 
}