~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/loader/i386/multiboot_mbi.c

Tags: upstream-1.99~20101122
ImportĀ upstreamĀ versionĀ 1.99~20101122

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
}