2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2011,2012,2013 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 #include <grub/lib/cmdline.h>
40 #if defined (GRUB_MACHINE_EFI)
41 #include <grub/efi/efi.h>
44 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
45 #include <grub/i386/pc/vbe.h>
46 #define HAS_VGA_TEXT 1
48 #define HAS_VGA_TEXT 0
60 static struct module
*modules
, *modules_last
;
61 static grub_size_t cmdline_size
;
62 static grub_size_t total_modcmd
;
63 static unsigned modcnt
;
64 static char *cmdline
= NULL
;
65 static int bootdev_set
;
66 static grub_uint32_t biosdev
, slice
, part
;
67 static grub_size_t elf_sec_num
, elf_sec_entsize
;
68 static unsigned elf_sec_shstrndx
;
69 static void *elf_sections
;
70 static int keep_bs
= 0;
73 grub_multiboot_add_elfsyms (grub_size_t num
, grub_size_t entsize
,
74 unsigned shndx
, void *data
)
77 elf_sec_shstrndx
= shndx
;
78 elf_sec_entsize
= entsize
;
82 static struct multiboot_header
*
83 find_header (grub_properly_aligned_t
*buffer
, grub_ssize_t len
)
85 struct multiboot_header
*header
;
86 /* Look for the multiboot header in the buffer. The header should
87 be at least 12 bytes and aligned on a 4-byte boundary. */
88 for (header
= (struct multiboot_header
*) buffer
;
89 ((char *) header
<= (char *) buffer
+ len
- 12);
90 header
= (struct multiboot_header
*) ((grub_uint32_t
*) header
+ MULTIBOOT_HEADER_ALIGN
/ 4))
92 if (header
->magic
== MULTIBOOT_HEADER_MAGIC
93 && !(header
->magic
+ header
->architecture
94 + header
->header_length
+ header
->checksum
)
95 && header
->architecture
== MULTIBOOT_ARCHITECTURE_CURRENT
)
102 grub_multiboot_load (grub_file_t file
, const char *filename
)
104 grub_properly_aligned_t
*buffer
;
106 struct multiboot_header
*header
;
108 struct multiboot_header_tag
*tag
;
109 struct multiboot_header_tag_address
*addr_tag
= NULL
;
110 int entry_specified
= 0;
111 grub_addr_t entry
= 0;
112 grub_uint32_t console_required
= 0;
113 struct multiboot_header_tag_framebuffer
*fbtag
= NULL
;
114 int accepted_consoles
= GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
116 buffer
= grub_malloc (MULTIBOOT_SEARCH
);
120 len
= grub_file_read (file
, buffer
, MULTIBOOT_SEARCH
);
124 return grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), filename
);
127 COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN
% 4 == 0);
129 header
= find_header (buffer
, len
);
134 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no multiboot header found");
137 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% 4 == 0);
141 for (tag
= (struct multiboot_header_tag
*) (header
+ 1);
142 tag
->type
!= MULTIBOOT_TAG_TYPE_END
;
143 tag
= (struct multiboot_header_tag
*) ((grub_uint32_t
*) tag
+ ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
) / 4))
146 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
:
149 struct multiboot_header_tag_information_request
*request_tag
150 = (struct multiboot_header_tag_information_request
*) tag
;
151 if (request_tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
)
153 for (i
= 0; i
< (request_tag
->size
- sizeof (request_tag
))
154 / sizeof (request_tag
->requests
[0]); i
++)
155 switch (request_tag
->requests
[i
])
157 case MULTIBOOT_TAG_TYPE_END
:
158 case MULTIBOOT_TAG_TYPE_CMDLINE
:
159 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
:
160 case MULTIBOOT_TAG_TYPE_MODULE
:
161 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
:
162 case MULTIBOOT_TAG_TYPE_BOOTDEV
:
163 case MULTIBOOT_TAG_TYPE_MMAP
:
164 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER
:
165 case MULTIBOOT_TAG_TYPE_VBE
:
166 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS
:
167 case MULTIBOOT_TAG_TYPE_APM
:
168 case MULTIBOOT_TAG_TYPE_EFI32
:
169 case MULTIBOOT_TAG_TYPE_EFI64
:
170 case MULTIBOOT_TAG_TYPE_ACPI_OLD
:
171 case MULTIBOOT_TAG_TYPE_ACPI_NEW
:
172 case MULTIBOOT_TAG_TYPE_NETWORK
:
173 case MULTIBOOT_TAG_TYPE_EFI_MMAP
:
174 case MULTIBOOT_TAG_TYPE_EFI_BS
:
179 return grub_error (GRUB_ERR_UNKNOWN_OS
,
180 "unsupported information tag: 0x%x",
181 request_tag
->requests
[i
]);
186 case MULTIBOOT_HEADER_TAG_ADDRESS
:
187 addr_tag
= (struct multiboot_header_tag_address
*) tag
;
190 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
:
192 entry
= ((struct multiboot_header_tag_entry_address
*) tag
)->entry_addr
;
195 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS
:
196 if (!(((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
197 & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
))
198 accepted_consoles
&= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
199 if (((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
200 & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED
)
201 console_required
= 1;
204 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER
:
205 fbtag
= (struct multiboot_header_tag_framebuffer
*) tag
;
206 accepted_consoles
|= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
;
209 /* GRUB always page-aligns modules. */
210 case MULTIBOOT_HEADER_TAG_MODULE_ALIGN
:
213 case MULTIBOOT_HEADER_TAG_EFI_BS
:
218 if (! (tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
))
221 return grub_error (GRUB_ERR_UNKNOWN_OS
,
222 "unsupported tag: 0x%x", tag
->type
);
227 if (addr_tag
&& !entry_specified
)
230 return grub_error (GRUB_ERR_UNKNOWN_OS
,
231 "load address tag without entry address tag");
236 grub_uint64_t load_addr
= (addr_tag
->load_addr
+ 1)
237 ? addr_tag
->load_addr
: (addr_tag
->header_addr
238 - ((char *) header
- (char *) buffer
));
239 int offset
= ((char *) header
- (char *) buffer
-
240 (addr_tag
->header_addr
- load_addr
));
241 int load_size
= ((addr_tag
->load_end_addr
== 0) ? file
->size
- offset
:
242 addr_tag
->load_end_addr
- addr_tag
->load_addr
);
243 grub_size_t code_size
;
245 grub_relocator_chunk_t ch
;
247 if (addr_tag
->bss_end_addr
)
248 code_size
= (addr_tag
->bss_end_addr
- load_addr
);
250 code_size
= load_size
;
252 err
= grub_relocator_alloc_chunk_addr (grub_multiboot_relocator
,
257 grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
261 source
= get_virtual_current_address (ch
);
263 if ((grub_file_seek (file
, offset
)) == (grub_off_t
) -1)
269 grub_file_read (file
, source
, load_size
);
276 if (addr_tag
->bss_end_addr
)
277 grub_memset ((grub_uint8_t
*) source
+ load_size
, 0,
278 addr_tag
->bss_end_addr
- load_addr
- load_size
);
282 err
= grub_multiboot_load_elf (file
, filename
, buffer
);
291 grub_multiboot_payload_eip
= entry
;
294 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
,
296 fbtag
->width
, fbtag
->height
,
297 fbtag
->depth
, console_required
);
299 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
,
301 0, 0, 0, console_required
);
308 #if GRUB_MACHINE_HAS_ACPI
309 struct grub_acpi_rsdp_v20
*p
= grub_acpi_get_rsdpv2 ();
314 return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
315 + p
->length
, MULTIBOOT_TAG_ALIGN
);
321 #ifdef GRUB_MACHINE_EFI
323 static grub_efi_uintn_t efi_mmap_size
= 0;
325 /* Find the optimal number of pages for the memory map. Is it better to
326 move this code to efi/mm.c? */
328 find_efi_mmap_size (void)
330 efi_mmap_size
= (1 << 12);
334 grub_efi_memory_descriptor_t
*mmap
;
335 grub_efi_uintn_t desc_size
;
336 grub_efi_uintn_t cur_mmap_size
= efi_mmap_size
;
338 mmap
= grub_malloc (cur_mmap_size
);
342 ret
= grub_efi_get_memory_map (&cur_mmap_size
, mmap
, 0, &desc_size
, 0);
350 if (efi_mmap_size
< cur_mmap_size
)
351 efi_mmap_size
= cur_mmap_size
;
352 efi_mmap_size
+= (1 << 12);
355 /* Increase the size a bit for safety, because GRUB allocates more on
356 later, and EFI itself may allocate more. */
357 efi_mmap_size
+= (3 << 12);
359 efi_mmap_size
= ALIGN_UP (efi_mmap_size
, 4096);
366 struct grub_net_network_level_interface
*net
;
369 FOR_NET_NETWORK_LEVEL_INTERFACES(net
)
371 ret
+= ALIGN_UP (sizeof (struct multiboot_tag_network
) + net
->dhcp_acklen
,
372 MULTIBOOT_TAG_ALIGN
);
377 grub_multiboot_get_mbi_size (void)
379 #ifdef GRUB_MACHINE_EFI
381 find_efi_mmap_size ();
383 return 2 * sizeof (grub_uint32_t
) + sizeof (struct multiboot_tag
)
384 + sizeof (struct multiboot_tag
)
385 + (sizeof (struct multiboot_tag_string
)
386 + ALIGN_UP (cmdline_size
, MULTIBOOT_TAG_ALIGN
))
387 + (sizeof (struct multiboot_tag_string
)
388 + ALIGN_UP (sizeof (PACKAGE_STRING
), MULTIBOOT_TAG_ALIGN
))
389 + (modcnt
* sizeof (struct multiboot_tag_module
) + total_modcmd
)
390 + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo
),
392 + ALIGN_UP (sizeof (struct multiboot_tag_bootdev
), MULTIBOOT_TAG_ALIGN
)
393 + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections
), MULTIBOOT_TAG_ALIGN
)
394 + ALIGN_UP (elf_sec_entsize
* elf_sec_num
, MULTIBOOT_TAG_ALIGN
)
395 + ALIGN_UP ((sizeof (struct multiboot_tag_mmap
)
396 + grub_get_multiboot_mmap_count ()
397 * sizeof (struct multiboot_mmap_entry
)), MULTIBOOT_TAG_ALIGN
)
398 + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer
), MULTIBOOT_TAG_ALIGN
)
399 + ALIGN_UP (sizeof (struct multiboot_tag_efi32
), MULTIBOOT_TAG_ALIGN
)
400 + ALIGN_UP (sizeof (struct multiboot_tag_efi64
), MULTIBOOT_TAG_ALIGN
)
401 + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
402 + sizeof (struct grub_acpi_rsdp_v10
), MULTIBOOT_TAG_ALIGN
)
405 #ifdef GRUB_MACHINE_EFI
406 + ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap
)
407 + efi_mmap_size
, MULTIBOOT_TAG_ALIGN
)
409 + sizeof (struct multiboot_tag_vbe
) + MULTIBOOT_TAG_ALIGN
- 1
410 + sizeof (struct multiboot_tag_apm
) + MULTIBOOT_TAG_ALIGN
- 1;
413 /* Helper for grub_fill_multiboot_mmap. */
415 grub_fill_multiboot_mmap_iter (grub_uint64_t addr
, grub_uint64_t size
,
416 grub_memory_type_t type
, void *data
)
418 struct multiboot_mmap_entry
**mmap_entry
= data
;
420 (*mmap_entry
)->addr
= addr
;
421 (*mmap_entry
)->len
= size
;
422 (*mmap_entry
)->type
= type
;
428 /* Fill previously allocated Multiboot mmap. */
430 grub_fill_multiboot_mmap (struct multiboot_tag_mmap
*tag
)
432 struct multiboot_mmap_entry
*mmap_entry
= tag
->entries
;
434 tag
->type
= MULTIBOOT_TAG_TYPE_MMAP
;
435 tag
->size
= sizeof (struct multiboot_tag_mmap
)
436 + sizeof (struct multiboot_mmap_entry
) * grub_get_multiboot_mmap_count ();
437 tag
->entry_size
= sizeof (struct multiboot_mmap_entry
);
438 tag
->entry_version
= 0;
440 grub_mmap_iterate (grub_fill_multiboot_mmap_iter
, &mmap_entry
);
443 #if defined (GRUB_MACHINE_PCBIOS)
445 fill_vbe_tag (struct multiboot_tag_vbe
*tag
)
447 grub_vbe_status_t status
;
448 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
450 tag
->type
= MULTIBOOT_TAG_TYPE_VBE
;
453 status
= grub_vbe_bios_get_controller_info (scratch
);
454 if (status
!= GRUB_VBE_STATUS_OK
)
457 grub_memcpy (&tag
->vbe_control_info
, scratch
,
458 sizeof (struct grub_vbe_info_block
));
460 status
= grub_vbe_bios_get_mode (scratch
);
461 tag
->vbe_mode
= *(grub_uint32_t
*) scratch
;
462 if (status
!= GRUB_VBE_STATUS_OK
)
465 /* get_mode_info isn't available for mode 3. */
466 if (tag
->vbe_mode
== 3)
468 struct grub_vbe_mode_info_block
*mode_info
= (void *) &tag
->vbe_mode_info
;
469 grub_memset (mode_info
, 0,
470 sizeof (struct grub_vbe_mode_info_block
));
471 mode_info
->memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
472 mode_info
->x_resolution
= 80;
473 mode_info
->y_resolution
= 25;
477 status
= grub_vbe_bios_get_mode_info (tag
->vbe_mode
, scratch
);
478 if (status
!= GRUB_VBE_STATUS_OK
)
480 grub_memcpy (&tag
->vbe_mode_info
, scratch
,
481 sizeof (struct grub_vbe_mode_info_block
));
483 grub_vbe_bios_get_pm_interface (&tag
->vbe_interface_seg
,
484 &tag
->vbe_interface_off
,
485 &tag
->vbe_interface_len
);
487 tag
->size
= sizeof (*tag
);
492 retrieve_video_parameters (grub_properly_aligned_t
**ptrorig
)
495 struct grub_video_mode_info mode_info
;
497 grub_video_driver_id_t driv_id
;
498 struct grub_video_palette_data palette
[256];
499 struct multiboot_tag_framebuffer
*tag
500 = (struct multiboot_tag_framebuffer
*) *ptrorig
;
502 err
= grub_multiboot_set_video_mode ();
506 grub_errno
= GRUB_ERR_NONE
;
509 grub_video_get_palette (0, ARRAY_SIZE (palette
), palette
);
511 driv_id
= grub_video_get_driver_id ();
513 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
515 struct grub_vbe_mode_info_block vbe_mode_info
;
516 grub_uint32_t vbe_mode
;
518 #if defined (GRUB_MACHINE_PCBIOS)
520 grub_vbe_status_t status
;
521 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
522 status
= grub_vbe_bios_get_mode (scratch
);
523 vbe_mode
= *(grub_uint32_t
*) scratch
;
524 if (status
!= GRUB_VBE_STATUS_OK
)
525 return GRUB_ERR_NONE
;
531 /* get_mode_info isn't available for mode 3. */
534 grub_memset (&vbe_mode_info
, 0,
535 sizeof (struct grub_vbe_mode_info_block
));
536 vbe_mode_info
.memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
537 vbe_mode_info
.x_resolution
= 80;
538 vbe_mode_info
.y_resolution
= 25;
540 #if defined (GRUB_MACHINE_PCBIOS)
543 grub_vbe_status_t status
;
544 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
545 status
= grub_vbe_bios_get_mode_info (vbe_mode
, scratch
);
546 if (status
!= GRUB_VBE_STATUS_OK
)
547 return GRUB_ERR_NONE
;
548 grub_memcpy (&vbe_mode_info
, scratch
,
549 sizeof (struct grub_vbe_mode_info_block
));
553 if (vbe_mode_info
.memory_model
== GRUB_VBE_MEMORY_MODEL_TEXT
)
555 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
556 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
557 tag
->common
.size
= 0;
559 tag
->common
.framebuffer_addr
= 0xb8000;
561 tag
->common
.framebuffer_pitch
= 2 * vbe_mode_info
.x_resolution
;
562 tag
->common
.framebuffer_width
= vbe_mode_info
.x_resolution
;
563 tag
->common
.framebuffer_height
= vbe_mode_info
.y_resolution
;
565 tag
->common
.framebuffer_bpp
= 16;
567 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT
;
568 tag
->common
.size
= sizeof (tag
->common
);
569 tag
->common
.reserved
= 0;
570 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
571 / sizeof (grub_properly_aligned_t
);
573 return GRUB_ERR_NONE
;
576 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
577 return GRUB_ERR_NONE
;
580 #if GRUB_MACHINE_HAS_VBE
582 struct multiboot_tag_vbe
*tag_vbe
= (struct multiboot_tag_vbe
*) *ptrorig
;
584 fill_vbe_tag (tag_vbe
);
586 *ptrorig
+= ALIGN_UP (tag_vbe
->size
, MULTIBOOT_TAG_ALIGN
)
587 / sizeof (grub_properly_aligned_t
);
591 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
595 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
596 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
597 tag
->common
.size
= 0;
599 tag
->common
.framebuffer_addr
= (grub_addr_t
) framebuffer
;
600 tag
->common
.framebuffer_pitch
= mode_info
.pitch
;
602 tag
->common
.framebuffer_width
= mode_info
.width
;
603 tag
->common
.framebuffer_height
= mode_info
.height
;
605 tag
->common
.framebuffer_bpp
= mode_info
.bpp
;
607 tag
->common
.reserved
= 0;
609 if (mode_info
.mode_type
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
)
612 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED
;
613 tag
->framebuffer_palette_num_colors
= mode_info
.number_of_colors
;
614 if (tag
->framebuffer_palette_num_colors
> ARRAY_SIZE (palette
))
615 tag
->framebuffer_palette_num_colors
= ARRAY_SIZE (palette
);
616 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
)
617 + sizeof (multiboot_uint16_t
) + tag
->framebuffer_palette_num_colors
618 * sizeof (struct multiboot_color
);
619 for (i
= 0; i
< tag
->framebuffer_palette_num_colors
; i
++)
621 tag
->framebuffer_palette
[i
].red
= palette
[i
].r
;
622 tag
->framebuffer_palette
[i
].green
= palette
[i
].g
;
623 tag
->framebuffer_palette
[i
].blue
= palette
[i
].b
;
628 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_RGB
;
629 tag
->framebuffer_red_field_position
= mode_info
.red_field_pos
;
630 tag
->framebuffer_red_mask_size
= mode_info
.red_mask_size
;
631 tag
->framebuffer_green_field_position
= mode_info
.green_field_pos
;
632 tag
->framebuffer_green_mask_size
= mode_info
.green_mask_size
;
633 tag
->framebuffer_blue_field_position
= mode_info
.blue_field_pos
;
634 tag
->framebuffer_blue_mask_size
= mode_info
.blue_mask_size
;
636 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
) + 6;
638 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
639 / sizeof (grub_properly_aligned_t
);
641 return GRUB_ERR_NONE
;
645 grub_multiboot_make_mbi (grub_uint32_t
*target
)
647 grub_properly_aligned_t
*ptrorig
;
648 grub_properly_aligned_t
*mbistart
;
651 grub_relocator_chunk_t ch
;
653 bufsize
= grub_multiboot_get_mbi_size ();
655 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% sizeof (grub_properly_aligned_t
) == 0);
657 err
= grub_relocator_alloc_chunk_align (grub_multiboot_relocator
, &ch
,
658 0, 0xffffffff - bufsize
,
659 bufsize
, MULTIBOOT_TAG_ALIGN
,
660 GRUB_RELOCATOR_PREFERENCE_NONE
, 1);
664 ptrorig
= get_virtual_current_address (ch
);
665 #if defined (__i386__) || defined (__x86_64__)
666 *target
= get_physical_target_address (ch
);
667 #elif defined (__mips)
668 *target
= get_physical_target_address (ch
) | 0x80000000;
670 #error Please complete this
674 COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t
))
675 % sizeof (grub_properly_aligned_t
) == 0);
676 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
677 % sizeof (grub_properly_aligned_t
) == 0);
678 ptrorig
+= (2 * sizeof (grub_uint32_t
)) / sizeof (grub_properly_aligned_t
);
681 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
682 tag
->type
= MULTIBOOT_TAG_TYPE_CMDLINE
;
683 tag
->size
= sizeof (struct multiboot_tag_string
) + cmdline_size
;
684 grub_memcpy (tag
->string
, cmdline
, cmdline_size
);
685 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
686 / sizeof (grub_properly_aligned_t
);
690 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
691 tag
->type
= MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
;
692 tag
->size
= sizeof (struct multiboot_tag_string
) + sizeof (PACKAGE_STRING
);
693 grub_memcpy (tag
->string
, PACKAGE_STRING
, sizeof (PACKAGE_STRING
));
694 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
695 / sizeof (grub_properly_aligned_t
);
698 #ifdef GRUB_MACHINE_PCBIOS
700 struct grub_apm_info info
;
701 if (grub_apm_get_info (&info
))
703 struct multiboot_tag_apm
*tag
= (struct multiboot_tag_apm
*) ptrorig
;
705 tag
->type
= MULTIBOOT_TAG_TYPE_APM
;
706 tag
->size
= sizeof (struct multiboot_tag_apm
);
708 tag
->cseg
= info
.cseg
;
709 tag
->offset
= info
.offset
;
710 tag
->cseg_16
= info
.cseg_16
;
711 tag
->dseg
= info
.dseg
;
712 tag
->flags
= info
.flags
;
713 tag
->cseg_len
= info
.cseg_len
;
714 tag
->dseg_len
= info
.dseg_len
;
715 tag
->cseg_16_len
= info
.cseg_16_len
;
716 tag
->version
= info
.version
;
718 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
719 / sizeof (grub_properly_aligned_t
);
728 for (i
= 0, cur
= modules
; i
< modcnt
; i
++, cur
= cur
->next
)
730 struct multiboot_tag_module
*tag
731 = (struct multiboot_tag_module
*) ptrorig
;
732 tag
->type
= MULTIBOOT_TAG_TYPE_MODULE
;
733 tag
->size
= sizeof (struct multiboot_tag_module
) + cur
->cmdline_size
;
734 tag
->mod_start
= cur
->start
;
735 tag
->mod_end
= tag
->mod_start
+ cur
->size
;
736 grub_memcpy (tag
->cmdline
, cur
->cmdline
, cur
->cmdline_size
);
737 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
738 / sizeof (grub_properly_aligned_t
);
743 struct multiboot_tag_mmap
*tag
= (struct multiboot_tag_mmap
*) ptrorig
;
744 grub_fill_multiboot_mmap (tag
);
745 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
746 / sizeof (grub_properly_aligned_t
);
750 struct multiboot_tag_elf_sections
*tag
751 = (struct multiboot_tag_elf_sections
*) ptrorig
;
752 tag
->type
= MULTIBOOT_TAG_TYPE_ELF_SECTIONS
;
753 tag
->size
= sizeof (struct multiboot_tag_elf_sections
)
754 + elf_sec_entsize
* elf_sec_num
;
755 grub_memcpy (tag
->sections
, elf_sections
, elf_sec_entsize
* elf_sec_num
);
756 tag
->num
= elf_sec_num
;
757 tag
->entsize
= elf_sec_entsize
;
758 tag
->shndx
= elf_sec_shstrndx
;
759 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
760 / sizeof (grub_properly_aligned_t
);
764 struct multiboot_tag_basic_meminfo
*tag
765 = (struct multiboot_tag_basic_meminfo
*) ptrorig
;
766 tag
->type
= MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
;
767 tag
->size
= sizeof (struct multiboot_tag_basic_meminfo
);
769 /* Convert from bytes to kilobytes. */
770 tag
->mem_lower
= grub_mmap_get_lower () / 1024;
771 tag
->mem_upper
= grub_mmap_get_upper () / 1024;
772 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
773 / sizeof (grub_properly_aligned_t
);
777 struct grub_net_network_level_interface
*net
;
779 FOR_NET_NETWORK_LEVEL_INTERFACES(net
)
782 struct multiboot_tag_network
*tag
783 = (struct multiboot_tag_network
*) ptrorig
;
784 tag
->type
= MULTIBOOT_TAG_TYPE_NETWORK
;
785 tag
->size
= sizeof (struct multiboot_tag_network
) + net
->dhcp_acklen
;
786 grub_memcpy (tag
->dhcpack
, net
->dhcp_ack
, net
->dhcp_acklen
);
787 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
788 / sizeof (grub_properly_aligned_t
);
794 struct multiboot_tag_bootdev
*tag
795 = (struct multiboot_tag_bootdev
*) ptrorig
;
796 tag
->type
= MULTIBOOT_TAG_TYPE_BOOTDEV
;
797 tag
->size
= sizeof (struct multiboot_tag_bootdev
);
799 tag
->biosdev
= biosdev
;
802 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
803 / sizeof (grub_properly_aligned_t
);
807 err
= retrieve_video_parameters (&ptrorig
);
811 grub_errno
= GRUB_ERR_NONE
;
815 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
817 struct multiboot_tag_efi64
*tag
= (struct multiboot_tag_efi64
*) ptrorig
;
818 tag
->type
= MULTIBOOT_TAG_TYPE_EFI64
;
819 tag
->size
= sizeof (*tag
);
820 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
821 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
822 / sizeof (grub_properly_aligned_t
);
826 #if defined (GRUB_MACHINE_EFI) && defined (__i386__)
828 struct multiboot_tag_efi32
*tag
= (struct multiboot_tag_efi32
*) ptrorig
;
829 tag
->type
= MULTIBOOT_TAG_TYPE_EFI32
;
830 tag
->size
= sizeof (*tag
);
831 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
832 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
833 / sizeof (grub_properly_aligned_t
);
837 #if GRUB_MACHINE_HAS_ACPI
839 struct multiboot_tag_old_acpi
*tag
= (struct multiboot_tag_old_acpi
*)
841 struct grub_acpi_rsdp_v10
*a
= grub_acpi_get_rsdpv1 ();
844 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_OLD
;
845 tag
->size
= sizeof (*tag
) + sizeof (*a
);
846 grub_memcpy (tag
->rsdp
, a
, sizeof (*a
));
847 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
848 / sizeof (grub_properly_aligned_t
);
853 struct multiboot_tag_new_acpi
*tag
= (struct multiboot_tag_new_acpi
*)
855 struct grub_acpi_rsdp_v20
*a
= grub_acpi_get_rsdpv2 ();
858 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_NEW
;
859 tag
->size
= sizeof (*tag
) + a
->length
;
860 grub_memcpy (tag
->rsdp
, a
, a
->length
);
861 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
862 / sizeof (grub_properly_aligned_t
);
867 #ifdef GRUB_MACHINE_EFI
869 struct multiboot_tag_efi_mmap
*tag
= (struct multiboot_tag_efi_mmap
*) ptrorig
;
870 grub_efi_uintn_t efi_desc_size
;
871 grub_efi_uint32_t efi_desc_version
;
873 tag
->type
= MULTIBOOT_TAG_TYPE_EFI_MMAP
;
874 tag
->size
= sizeof (*tag
) + efi_mmap_size
;
877 err
= grub_efi_finish_boot_services (&efi_mmap_size
, tag
->efi_mmap
, NULL
,
878 &efi_desc_size
, &efi_desc_version
);
881 if (grub_efi_get_memory_map (&efi_mmap_size
, (void *) tag
->efi_mmap
,
883 &efi_desc_size
, &efi_desc_version
) <= 0)
884 err
= grub_error (GRUB_ERR_IO
, "couldn't retrieve memory map");
888 tag
->descr_size
= efi_desc_size
;
889 tag
->descr_vers
= efi_desc_version
;
890 tag
->size
= sizeof (*tag
) + efi_mmap_size
;
892 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
893 / sizeof (grub_properly_aligned_t
);
898 struct multiboot_tag
*tag
= (struct multiboot_tag
*) ptrorig
;
899 tag
->type
= MULTIBOOT_TAG_TYPE_EFI_BS
;
900 tag
->size
= sizeof (struct multiboot_tag
);
901 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
902 / sizeof (grub_properly_aligned_t
);
907 struct multiboot_tag
*tag
= (struct multiboot_tag
*) ptrorig
;
908 tag
->type
= MULTIBOOT_TAG_TYPE_END
;
909 tag
->size
= sizeof (struct multiboot_tag
);
910 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
911 / sizeof (grub_properly_aligned_t
);
914 ((grub_uint32_t
*) mbistart
)[0] = (char *) ptrorig
- (char *) mbistart
;
915 ((grub_uint32_t
*) mbistart
)[1] = 0;
917 return GRUB_ERR_NONE
;
921 grub_multiboot_free_mbi (void)
923 struct module
*cur
, *next
;
932 for (cur
= modules
; cur
; cur
= next
)
935 grub_free (cur
->cmdline
);
943 grub_multiboot_init_mbi (int argc
, char *argv
[])
945 grub_ssize_t len
= 0;
947 grub_multiboot_free_mbi ();
949 len
= grub_loader_cmdline_size (argc
, argv
);
951 cmdline
= grub_malloc (len
);
956 grub_create_loader_cmdline (argc
, argv
, cmdline
,
959 return GRUB_ERR_NONE
;
963 grub_multiboot_add_module (grub_addr_t start
, grub_size_t size
,
964 int argc
, char *argv
[])
966 struct module
*newmod
;
969 newmod
= grub_malloc (sizeof (*newmod
));
972 newmod
->start
= start
;
975 len
= grub_loader_cmdline_size (argc
, argv
);
977 newmod
->cmdline
= grub_malloc (len
);
978 if (! newmod
->cmdline
)
983 newmod
->cmdline_size
= len
;
984 total_modcmd
+= ALIGN_UP (len
, MULTIBOOT_TAG_ALIGN
);
986 grub_create_loader_cmdline (argc
, argv
, newmod
->cmdline
,
987 newmod
->cmdline_size
);
990 modules_last
->next
= newmod
;
993 modules_last
= newmod
;
997 return GRUB_ERR_NONE
;
1001 grub_multiboot_set_bootdev (void)
1008 #ifdef GRUB_MACHINE_PCBIOS
1009 biosdev
= grub_get_root_biosnumber ();
1011 biosdev
= 0xffffffff;
1014 if (biosdev
== 0xffffffff)
1017 dev
= grub_device_open (0);
1018 if (dev
&& dev
->disk
&& dev
->disk
->partition
)
1020 if (dev
->disk
->partition
->parent
)
1022 part
= dev
->disk
->partition
->number
;
1023 slice
= dev
->disk
->partition
->parent
->number
;
1026 slice
= dev
->disk
->partition
->number
;
1029 grub_device_close (dev
);