2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
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>
25 #include <grub/multiboot.h>
26 #include <grub/cpu/multiboot.h>
27 #include <grub/cpu/relocator.h>
28 #include <grub/disk.h>
29 #include <grub/device.h>
30 #include <grub/partition.h>
32 #include <grub/misc.h>
34 #include <grub/video.h>
35 #include <grub/acpi.h>
36 #include <grub/i18n.h>
38 #if defined (GRUB_MACHINE_EFI)
39 #include <grub/efi/efi.h>
42 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
43 #include <grub/i386/pc/vbe.h>
44 #define HAS_VGA_TEXT 1
46 #define HAS_VGA_TEXT 0
58 static struct module
*modules
, *modules_last
;
59 static grub_size_t cmdline_size
;
60 static grub_size_t total_modcmd
;
61 static unsigned modcnt
;
62 static char *cmdline
= NULL
;
63 static int bootdev_set
;
64 static grub_uint32_t biosdev
, slice
, part
;
65 static grub_size_t elf_sec_num
, elf_sec_entsize
;
66 static unsigned elf_sec_shstrndx
;
67 static void *elf_sections
;
70 grub_multiboot_add_elfsyms (grub_size_t num
, grub_size_t entsize
,
71 unsigned shndx
, void *data
)
74 elf_sec_shstrndx
= shndx
;
75 elf_sec_entsize
= entsize
;
80 grub_multiboot_load (grub_file_t file
, const char *filename
)
82 grub_properly_aligned_t
*buffer
;
84 struct multiboot_header
*header
;
86 struct multiboot_header_tag
*tag
;
87 struct multiboot_header_tag_address
*addr_tag
= NULL
;
88 int entry_specified
= 0;
89 grub_addr_t entry
= 0;
90 grub_uint32_t console_required
= 0;
91 struct multiboot_header_tag_framebuffer
*fbtag
= NULL
;
92 int accepted_consoles
= GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
94 buffer
= grub_malloc (MULTIBOOT_SEARCH
);
98 len
= grub_file_read (file
, buffer
, MULTIBOOT_SEARCH
);
102 return grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), filename
);
105 COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN
% 4 == 0);
107 /* Look for the multiboot header in the buffer. The header should
108 be at least 12 bytes and aligned on a 4-byte boundary. */
109 for (header
= (struct multiboot_header
*) buffer
;
110 ((char *) header
<= (char *) buffer
+ len
- 12) || (header
= 0);
111 header
= (struct multiboot_header
*) ((grub_uint32_t
*) header
+ MULTIBOOT_HEADER_ALIGN
/ 4))
113 if (header
->magic
== MULTIBOOT_HEADER_MAGIC
114 && !(header
->magic
+ header
->architecture
115 + header
->header_length
+ header
->checksum
)
116 && header
->architecture
== MULTIBOOT_ARCHITECTURE_CURRENT
)
123 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no multiboot header found");
126 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% 4 == 0);
128 for (tag
= (struct multiboot_header_tag
*) (header
+ 1);
129 tag
->type
!= MULTIBOOT_TAG_TYPE_END
;
130 tag
= (struct multiboot_header_tag
*) ((grub_uint32_t
*) tag
+ ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
) / 4))
133 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
:
136 struct multiboot_header_tag_information_request
*request_tag
137 = (struct multiboot_header_tag_information_request
*) tag
;
138 if (request_tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
)
140 for (i
= 0; i
< (request_tag
->size
- sizeof (request_tag
))
141 / sizeof (request_tag
->requests
[0]); i
++)
142 switch (request_tag
->requests
[i
])
144 case MULTIBOOT_TAG_TYPE_END
:
145 case MULTIBOOT_TAG_TYPE_CMDLINE
:
146 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
:
147 case MULTIBOOT_TAG_TYPE_MODULE
:
148 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
:
149 case MULTIBOOT_TAG_TYPE_BOOTDEV
:
150 case MULTIBOOT_TAG_TYPE_MMAP
:
151 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER
:
152 case MULTIBOOT_TAG_TYPE_VBE
:
153 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS
:
154 case MULTIBOOT_TAG_TYPE_APM
:
155 case MULTIBOOT_TAG_TYPE_EFI32
:
156 case MULTIBOOT_TAG_TYPE_EFI64
:
157 case MULTIBOOT_TAG_TYPE_ACPI_OLD
:
158 case MULTIBOOT_TAG_TYPE_ACPI_NEW
:
163 return grub_error (GRUB_ERR_UNKNOWN_OS
,
164 "unsupported information tag: 0x%x",
165 request_tag
->requests
[i
]);
170 case MULTIBOOT_HEADER_TAG_ADDRESS
:
171 addr_tag
= (struct multiboot_header_tag_address
*) tag
;
174 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
:
176 entry
= ((struct multiboot_header_tag_entry_address
*) tag
)->entry_addr
;
179 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS
:
180 if (!(((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
181 & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
))
182 accepted_consoles
&= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
183 if (((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
184 & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED
)
185 console_required
= 1;
188 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER
:
189 fbtag
= (struct multiboot_header_tag_framebuffer
*) tag
;
190 accepted_consoles
|= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
;
193 /* GRUB always page-aligns modules. */
194 case MULTIBOOT_HEADER_TAG_MODULE_ALIGN
:
198 if (! (tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
))
201 return grub_error (GRUB_ERR_UNKNOWN_OS
,
202 "unsupported tag: 0x%x", tag
->type
);
207 if (addr_tag
&& !entry_specified
)
210 return grub_error (GRUB_ERR_UNKNOWN_OS
,
211 "load address tag without entry address tag");
216 int offset
= ((char *) header
- (char *) buffer
-
217 (addr_tag
->header_addr
- addr_tag
->load_addr
));
218 int load_size
= ((addr_tag
->load_end_addr
== 0) ? file
->size
- offset
:
219 addr_tag
->load_end_addr
- addr_tag
->load_addr
);
220 grub_size_t code_size
;
222 grub_relocator_chunk_t ch
;
224 if (addr_tag
->bss_end_addr
)
225 code_size
= (addr_tag
->bss_end_addr
- addr_tag
->load_addr
);
227 code_size
= load_size
;
229 err
= grub_relocator_alloc_chunk_addr (grub_multiboot_relocator
,
230 &ch
, addr_tag
->load_addr
,
234 grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
238 source
= get_virtual_current_address (ch
);
240 if ((grub_file_seek (file
, offset
)) == (grub_off_t
) -1)
246 grub_file_read (file
, source
, load_size
);
253 if (addr_tag
->bss_end_addr
)
254 grub_memset ((grub_uint32_t
*) source
+ load_size
, 0,
255 addr_tag
->bss_end_addr
- addr_tag
->load_addr
- load_size
);
259 err
= grub_multiboot_load_elf (file
, filename
, buffer
);
268 grub_multiboot_payload_eip
= entry
;
271 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
,
273 fbtag
->width
, fbtag
->height
,
274 fbtag
->depth
, console_required
);
276 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
,
278 0, 0, 0, console_required
);
285 #if GRUB_MACHINE_HAS_ACPI
286 struct grub_acpi_rsdp_v20
*p
= grub_acpi_get_rsdpv2 ();
291 return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
292 + p
->length
, MULTIBOOT_TAG_ALIGN
);
299 grub_multiboot_get_mbi_size (void)
301 return 2 * sizeof (grub_uint32_t
) + sizeof (struct multiboot_tag
)
302 + (sizeof (struct multiboot_tag_string
)
303 + ALIGN_UP (cmdline_size
, MULTIBOOT_TAG_ALIGN
))
304 + (sizeof (struct multiboot_tag_string
)
305 + ALIGN_UP (sizeof (PACKAGE_STRING
), MULTIBOOT_TAG_ALIGN
))
306 + (modcnt
* sizeof (struct multiboot_tag_module
) + total_modcmd
)
307 + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo
),
309 + ALIGN_UP (sizeof (struct multiboot_tag_bootdev
), MULTIBOOT_TAG_ALIGN
)
310 + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections
), MULTIBOOT_TAG_ALIGN
)
311 + ALIGN_UP (elf_sec_entsize
* elf_sec_num
, MULTIBOOT_TAG_ALIGN
)
312 + ALIGN_UP ((sizeof (struct multiboot_tag_mmap
)
313 + grub_get_multiboot_mmap_count ()
314 * sizeof (struct multiboot_mmap_entry
)), MULTIBOOT_TAG_ALIGN
)
315 + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer
), MULTIBOOT_TAG_ALIGN
)
316 + ALIGN_UP (sizeof (struct multiboot_tag_efi32
), MULTIBOOT_TAG_ALIGN
)
317 + ALIGN_UP (sizeof (struct multiboot_tag_efi64
), MULTIBOOT_TAG_ALIGN
)
318 + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
319 + sizeof (struct grub_acpi_rsdp_v10
), MULTIBOOT_TAG_ALIGN
)
321 + sizeof (struct multiboot_tag_vbe
) + MULTIBOOT_TAG_ALIGN
- 1
322 + sizeof (struct multiboot_tag_apm
) + MULTIBOOT_TAG_ALIGN
- 1;
325 /* Fill previously allocated Multiboot mmap. */
327 grub_fill_multiboot_mmap (struct multiboot_tag_mmap
*tag
)
329 struct multiboot_mmap_entry
*mmap_entry
= tag
->entries
;
331 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
,
333 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
,
334 grub_memory_type_t type
)
336 mmap_entry
->addr
= addr
;
337 mmap_entry
->len
= size
;
340 case GRUB_MEMORY_AVAILABLE
:
341 mmap_entry
->type
= MULTIBOOT_MEMORY_AVAILABLE
;
344 case GRUB_MEMORY_ACPI
:
345 mmap_entry
->type
= MULTIBOOT_MEMORY_ACPI_RECLAIMABLE
;
348 case GRUB_MEMORY_NVS
:
349 mmap_entry
->type
= MULTIBOOT_MEMORY_NVS
;
352 case GRUB_MEMORY_BADRAM
:
353 mmap_entry
->type
= MULTIBOOT_MEMORY_BADRAM
;
357 mmap_entry
->type
= MULTIBOOT_MEMORY_RESERVED
;
365 tag
->type
= MULTIBOOT_TAG_TYPE_MMAP
;
366 tag
->size
= sizeof (struct multiboot_tag_mmap
)
367 + sizeof (struct multiboot_mmap_entry
) * grub_get_multiboot_mmap_count ();
368 tag
->entry_size
= sizeof (struct multiboot_mmap_entry
);
369 tag
->entry_version
= 0;
371 grub_mmap_iterate (hook
);
374 #if defined (GRUB_MACHINE_PCBIOS)
376 fill_vbe_tag (struct multiboot_tag_vbe
*tag
)
378 grub_vbe_status_t status
;
379 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
381 tag
->type
= MULTIBOOT_TAG_TYPE_VBE
;
384 status
= grub_vbe_bios_get_controller_info (scratch
);
385 if (status
!= GRUB_VBE_STATUS_OK
)
388 grub_memcpy (&tag
->vbe_control_info
, scratch
,
389 sizeof (struct grub_vbe_info_block
));
391 status
= grub_vbe_bios_get_mode (scratch
);
392 tag
->vbe_mode
= *(grub_uint32_t
*) scratch
;
393 if (status
!= GRUB_VBE_STATUS_OK
)
396 /* get_mode_info isn't available for mode 3. */
397 if (tag
->vbe_mode
== 3)
399 struct grub_vbe_mode_info_block
*mode_info
= (void *) &tag
->vbe_mode_info
;
400 grub_memset (mode_info
, 0,
401 sizeof (struct grub_vbe_mode_info_block
));
402 mode_info
->memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
403 mode_info
->x_resolution
= 80;
404 mode_info
->y_resolution
= 25;
408 status
= grub_vbe_bios_get_mode_info (tag
->vbe_mode
, scratch
);
409 if (status
!= GRUB_VBE_STATUS_OK
)
411 grub_memcpy (&tag
->vbe_mode_info
, scratch
,
412 sizeof (struct grub_vbe_mode_info_block
));
414 grub_vbe_bios_get_pm_interface (&tag
->vbe_interface_seg
,
415 &tag
->vbe_interface_off
,
416 &tag
->vbe_interface_len
);
418 tag
->size
= sizeof (*tag
);
423 retrieve_video_parameters (grub_properly_aligned_t
**ptrorig
)
426 struct grub_video_mode_info mode_info
;
428 grub_video_driver_id_t driv_id
;
429 struct grub_video_palette_data palette
[256];
430 struct multiboot_tag_framebuffer
*tag
431 = (struct multiboot_tag_framebuffer
*) *ptrorig
;
433 err
= grub_multiboot_set_video_mode ();
437 grub_errno
= GRUB_ERR_NONE
;
440 grub_video_get_palette (0, ARRAY_SIZE (palette
), palette
);
442 driv_id
= grub_video_get_driver_id ();
444 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
446 struct grub_vbe_mode_info_block vbe_mode_info
;
447 grub_uint32_t vbe_mode
;
449 #if defined (GRUB_MACHINE_PCBIOS)
451 grub_vbe_status_t status
;
452 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
453 status
= grub_vbe_bios_get_mode (scratch
);
454 vbe_mode
= *(grub_uint32_t
*) scratch
;
455 if (status
!= GRUB_VBE_STATUS_OK
)
456 return GRUB_ERR_NONE
;
462 /* get_mode_info isn't available for mode 3. */
465 grub_memset (&vbe_mode_info
, 0,
466 sizeof (struct grub_vbe_mode_info_block
));
467 vbe_mode_info
.memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
468 vbe_mode_info
.x_resolution
= 80;
469 vbe_mode_info
.y_resolution
= 25;
471 #if defined (GRUB_MACHINE_PCBIOS)
474 grub_vbe_status_t status
;
475 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
476 status
= grub_vbe_bios_get_mode_info (vbe_mode
, scratch
);
477 if (status
!= GRUB_VBE_STATUS_OK
)
478 return GRUB_ERR_NONE
;
479 grub_memcpy (&vbe_mode_info
, scratch
,
480 sizeof (struct grub_vbe_mode_info_block
));
484 if (vbe_mode_info
.memory_model
== GRUB_VBE_MEMORY_MODEL_TEXT
)
486 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
487 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
488 tag
->common
.size
= 0;
490 tag
->common
.framebuffer_addr
= 0xb8000;
492 tag
->common
.framebuffer_pitch
= 2 * vbe_mode_info
.x_resolution
;
493 tag
->common
.framebuffer_width
= vbe_mode_info
.x_resolution
;
494 tag
->common
.framebuffer_height
= vbe_mode_info
.y_resolution
;
496 tag
->common
.framebuffer_bpp
= 16;
498 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT
;
499 tag
->common
.size
= sizeof (tag
->common
);
500 tag
->common
.reserved
= 0;
501 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
502 / sizeof (grub_properly_aligned_t
);
504 return GRUB_ERR_NONE
;
507 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
508 return GRUB_ERR_NONE
;
511 #if GRUB_MACHINE_HAS_VBE
513 struct multiboot_tag_vbe
*tag_vbe
= (struct multiboot_tag_vbe
*) *ptrorig
;
515 fill_vbe_tag (tag_vbe
);
517 *ptrorig
+= ALIGN_UP (tag_vbe
->size
, MULTIBOOT_TAG_ALIGN
)
518 / sizeof (grub_properly_aligned_t
);
522 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
526 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
527 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
528 tag
->common
.size
= 0;
530 tag
->common
.framebuffer_addr
= (grub_addr_t
) framebuffer
;
531 tag
->common
.framebuffer_pitch
= mode_info
.pitch
;
533 tag
->common
.framebuffer_width
= mode_info
.width
;
534 tag
->common
.framebuffer_height
= mode_info
.height
;
536 tag
->common
.framebuffer_bpp
= mode_info
.bpp
;
538 tag
->common
.reserved
= 0;
540 if (mode_info
.mode_type
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
)
543 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED
;
544 tag
->framebuffer_palette_num_colors
= mode_info
.number_of_colors
;
545 if (tag
->framebuffer_palette_num_colors
> ARRAY_SIZE (palette
))
546 tag
->framebuffer_palette_num_colors
= ARRAY_SIZE (palette
);
547 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
)
548 + sizeof (multiboot_uint16_t
) + tag
->framebuffer_palette_num_colors
549 * sizeof (struct multiboot_color
);
550 for (i
= 0; i
< tag
->framebuffer_palette_num_colors
; i
++)
552 tag
->framebuffer_palette
[i
].red
= palette
[i
].r
;
553 tag
->framebuffer_palette
[i
].green
= palette
[i
].g
;
554 tag
->framebuffer_palette
[i
].blue
= palette
[i
].b
;
559 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_RGB
;
560 tag
->framebuffer_red_field_position
= mode_info
.red_field_pos
;
561 tag
->framebuffer_red_mask_size
= mode_info
.red_mask_size
;
562 tag
->framebuffer_green_field_position
= mode_info
.green_field_pos
;
563 tag
->framebuffer_green_mask_size
= mode_info
.green_mask_size
;
564 tag
->framebuffer_blue_field_position
= mode_info
.blue_field_pos
;
565 tag
->framebuffer_blue_mask_size
= mode_info
.blue_mask_size
;
567 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
) + 6;
569 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
570 / sizeof (grub_properly_aligned_t
);
572 return GRUB_ERR_NONE
;
576 grub_multiboot_make_mbi (grub_uint32_t
*target
)
578 grub_properly_aligned_t
*ptrorig
;
579 grub_properly_aligned_t
*mbistart
;
582 grub_relocator_chunk_t ch
;
584 bufsize
= grub_multiboot_get_mbi_size ();
586 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% sizeof (grub_properly_aligned_t
) == 0);
588 err
= grub_relocator_alloc_chunk_align (grub_multiboot_relocator
, &ch
,
589 0, 0xffffffff - bufsize
,
590 bufsize
, MULTIBOOT_TAG_ALIGN
,
591 GRUB_RELOCATOR_PREFERENCE_NONE
, 0);
595 ptrorig
= get_virtual_current_address (ch
);
596 #if defined (__i386__) || defined (__x86_64__)
597 *target
= get_physical_target_address (ch
);
598 #elif defined (__mips)
599 *target
= get_physical_target_address (ch
) | 0x80000000;
601 #error Please complete this
605 COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t
))
606 % sizeof (grub_properly_aligned_t
) == 0);
607 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
608 % sizeof (grub_properly_aligned_t
) == 0);
609 ptrorig
+= (2 * sizeof (grub_uint32_t
)) / sizeof (grub_properly_aligned_t
);
612 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
613 tag
->type
= MULTIBOOT_TAG_TYPE_CMDLINE
;
614 tag
->size
= sizeof (struct multiboot_tag_string
) + cmdline_size
;
615 grub_memcpy (tag
->string
, cmdline
, cmdline_size
);
616 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
617 / sizeof (grub_properly_aligned_t
);
621 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
622 tag
->type
= MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
;
623 tag
->size
= sizeof (struct multiboot_tag_string
) + sizeof (PACKAGE_STRING
);
624 grub_memcpy (tag
->string
, PACKAGE_STRING
, sizeof (PACKAGE_STRING
));
625 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
626 / sizeof (grub_properly_aligned_t
);
629 #ifdef GRUB_MACHINE_PCBIOS
631 struct grub_apm_info info
;
632 if (grub_apm_get_info (&info
))
634 struct multiboot_tag_apm
*tag
= (struct multiboot_tag_apm
*) ptrorig
;
636 tag
->type
= MULTIBOOT_TAG_TYPE_APM
;
637 tag
->size
= sizeof (struct multiboot_tag_apm
);
639 tag
->cseg
= info
.cseg
;
640 tag
->offset
= info
.offset
;
641 tag
->cseg_16
= info
.cseg_16
;
642 tag
->dseg
= info
.dseg
;
643 tag
->flags
= info
.flags
;
644 tag
->cseg_len
= info
.cseg_len
;
645 tag
->dseg_len
= info
.dseg_len
;
646 tag
->cseg_16_len
= info
.cseg_16_len
;
647 tag
->version
= info
.version
;
649 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
650 / sizeof (grub_properly_aligned_t
);
659 for (i
= 0, cur
= modules
; i
< modcnt
; i
++, cur
= cur
->next
)
661 struct multiboot_tag_module
*tag
662 = (struct multiboot_tag_module
*) ptrorig
;
663 tag
->type
= MULTIBOOT_TAG_TYPE_MODULE
;
664 tag
->size
= sizeof (struct multiboot_tag_module
) + cur
->cmdline_size
;
665 tag
->mod_start
= cur
->start
;
666 tag
->mod_end
= tag
->mod_start
+ cur
->size
;
667 grub_memcpy (tag
->cmdline
, cur
->cmdline
, cur
->cmdline_size
);
668 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
669 / sizeof (grub_properly_aligned_t
);
674 struct multiboot_tag_mmap
*tag
= (struct multiboot_tag_mmap
*) ptrorig
;
675 grub_fill_multiboot_mmap (tag
);
676 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
677 / sizeof (grub_properly_aligned_t
);
681 struct multiboot_tag_elf_sections
*tag
682 = (struct multiboot_tag_elf_sections
*) ptrorig
;
683 tag
->type
= MULTIBOOT_TAG_TYPE_ELF_SECTIONS
;
684 tag
->size
= sizeof (struct multiboot_tag_elf_sections
)
685 + elf_sec_entsize
* elf_sec_num
;
686 grub_memcpy (tag
->sections
, elf_sections
, elf_sec_entsize
* elf_sec_num
);
687 tag
->num
= elf_sec_num
;
688 tag
->entsize
= elf_sec_entsize
;
689 tag
->shndx
= elf_sec_shstrndx
;
690 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
691 / sizeof (grub_properly_aligned_t
);
695 struct multiboot_tag_basic_meminfo
*tag
696 = (struct multiboot_tag_basic_meminfo
*) ptrorig
;
697 tag
->type
= MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
;
698 tag
->size
= sizeof (struct multiboot_tag_basic_meminfo
);
700 /* Convert from bytes to kilobytes. */
701 tag
->mem_lower
= grub_mmap_get_lower () / 1024;
702 tag
->mem_upper
= grub_mmap_get_upper () / 1024;
703 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
704 / sizeof (grub_properly_aligned_t
);
709 struct multiboot_tag_bootdev
*tag
710 = (struct multiboot_tag_bootdev
*) ptrorig
;
711 tag
->type
= MULTIBOOT_TAG_TYPE_BOOTDEV
;
712 tag
->size
= sizeof (struct multiboot_tag_bootdev
);
714 tag
->biosdev
= biosdev
;
717 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
718 / sizeof (grub_properly_aligned_t
);
722 err
= retrieve_video_parameters (&ptrorig
);
726 grub_errno
= GRUB_ERR_NONE
;
730 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
732 struct multiboot_tag_efi64
*tag
= (struct multiboot_tag_efi64
*) ptrorig
;
733 tag
->type
= MULTIBOOT_TAG_TYPE_EFI64
;
734 tag
->size
= sizeof (*tag
);
735 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
736 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
737 / sizeof (grub_properly_aligned_t
);
741 #if defined (GRUB_MACHINE_EFI) && defined (__i386__)
743 struct multiboot_tag_efi32
*tag
= (struct multiboot_tag_efi32
*) ptrorig
;
744 tag
->type
= MULTIBOOT_TAG_TYPE_EFI32
;
745 tag
->size
= sizeof (*tag
);
746 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
747 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
748 / sizeof (grub_properly_aligned_t
);
752 #if GRUB_MACHINE_HAS_ACPI
754 struct multiboot_tag_old_acpi
*tag
= (struct multiboot_tag_old_acpi
*)
756 struct grub_acpi_rsdp_v10
*a
= grub_acpi_get_rsdpv1 ();
759 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_OLD
;
760 tag
->size
= sizeof (*tag
) + sizeof (*a
);
761 grub_memcpy (tag
->rsdp
, a
, sizeof (*a
));
762 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
763 / sizeof (grub_properly_aligned_t
);
768 struct multiboot_tag_new_acpi
*tag
= (struct multiboot_tag_new_acpi
*)
770 struct grub_acpi_rsdp_v20
*a
= grub_acpi_get_rsdpv2 ();
773 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_NEW
;
774 tag
->size
= sizeof (*tag
) + a
->length
;
775 grub_memcpy (tag
->rsdp
, a
, a
->length
);
776 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
777 / sizeof (grub_properly_aligned_t
);
783 struct multiboot_tag
*tag
= (struct multiboot_tag
*) ptrorig
;
784 tag
->type
= MULTIBOOT_TAG_TYPE_END
;
785 tag
->size
= sizeof (struct multiboot_tag
);
786 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
787 / sizeof (grub_properly_aligned_t
);
790 ((grub_uint32_t
*) mbistart
)[0] = (char *) ptrorig
- (char *) mbistart
;
791 ((grub_uint32_t
*) mbistart
)[1] = 0;
793 return GRUB_ERR_NONE
;
797 grub_multiboot_free_mbi (void)
799 struct module
*cur
, *next
;
808 for (cur
= modules
; cur
; cur
= next
)
811 grub_free (cur
->cmdline
);
819 grub_multiboot_init_mbi (int argc
, char *argv
[])
821 grub_ssize_t len
= 0;
825 grub_multiboot_free_mbi ();
827 for (i
= 0; i
< argc
; i
++)
828 len
+= grub_strlen (argv
[i
]) + 1;
832 cmdline
= p
= grub_malloc (len
);
837 for (i
= 0; i
< argc
; i
++)
839 p
= grub_stpcpy (p
, argv
[i
]);
843 /* Remove the space after the last word. */
848 return GRUB_ERR_NONE
;
852 grub_multiboot_add_module (grub_addr_t start
, grub_size_t size
,
853 int argc
, char *argv
[])
855 struct module
*newmod
;
857 grub_ssize_t len
= 0;
860 newmod
= grub_malloc (sizeof (*newmod
));
863 newmod
->start
= start
;
866 for (i
= 0; i
< argc
; i
++)
867 len
+= grub_strlen (argv
[i
]) + 1;
872 newmod
->cmdline
= p
= grub_malloc (len
);
873 if (! newmod
->cmdline
)
878 newmod
->cmdline_size
= len
;
879 total_modcmd
+= ALIGN_UP (len
, MULTIBOOT_TAG_ALIGN
);
881 for (i
= 0; i
< argc
; i
++)
883 p
= grub_stpcpy (p
, argv
[i
]);
887 /* Remove the space after the last word. */
888 if (p
!= newmod
->cmdline
)
893 modules_last
->next
= newmod
;
897 modules_last
->next
= NULL
;
899 modules_last
= newmod
;
903 return GRUB_ERR_NONE
;
907 grub_multiboot_set_bootdev (void)
914 #ifdef GRUB_MACHINE_PCBIOS
915 biosdev
= grub_get_root_biosnumber ();
917 biosdev
= 0xffffffff;
920 if (biosdev
== 0xffffffff)
923 dev
= grub_device_open (0);
924 if (dev
&& dev
->disk
&& dev
->disk
->partition
)
926 if (dev
->disk
->partition
->parent
)
928 part
= dev
->disk
->partition
->number
;
929 slice
= dev
->disk
->partition
->parent
->number
;
932 slice
= dev
->disk
->partition
->number
;
935 grub_device_close (dev
);