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;
71 static grub_uint32_t load_base_addr
;
74 grub_multiboot_add_elfsyms (grub_size_t num
, grub_size_t entsize
,
75 unsigned shndx
, void *data
)
78 elf_sec_shstrndx
= shndx
;
79 elf_sec_entsize
= entsize
;
83 static struct multiboot_header
*
84 find_header (grub_properly_aligned_t
*buffer
, grub_ssize_t len
)
86 struct multiboot_header
*header
;
87 /* Look for the multiboot header in the buffer. The header should
88 be at least 12 bytes and aligned on a 4-byte boundary. */
89 for (header
= (struct multiboot_header
*) buffer
;
90 ((char *) header
<= (char *) buffer
+ len
- 12);
91 header
= (struct multiboot_header
*) ((grub_uint32_t
*) header
+ MULTIBOOT_HEADER_ALIGN
/ 4))
93 if (header
->magic
== MULTIBOOT_HEADER_MAGIC
94 && !(header
->magic
+ header
->architecture
95 + header
->header_length
+ header
->checksum
)
96 && header
->architecture
== MULTIBOOT_ARCHITECTURE_CURRENT
)
103 grub_multiboot_load (grub_file_t file
, const char *filename
)
106 struct multiboot_header
*header
;
108 struct multiboot_header_tag
*tag
;
109 struct multiboot_header_tag_address
*addr_tag
= NULL
;
110 struct multiboot_header_tag_relocatable
*rel_tag
;
111 int entry_specified
= 0, efi_entry_specified
= 0;
112 grub_addr_t entry
= 0, efi_entry
= 0;
113 grub_uint32_t console_required
= 0;
114 struct multiboot_header_tag_framebuffer
*fbtag
= NULL
;
115 int accepted_consoles
= GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
121 mld
.buffer
= grub_malloc (MULTIBOOT_SEARCH
);
125 len
= grub_file_read (file
, mld
.buffer
, MULTIBOOT_SEARCH
);
128 grub_free (mld
.buffer
);
129 return grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), filename
);
132 COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN
% 4 == 0);
134 header
= find_header (mld
.buffer
, len
);
138 grub_free (mld
.buffer
);
139 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no multiboot header found");
142 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% 4 == 0);
146 for (tag
= (struct multiboot_header_tag
*) (header
+ 1);
147 tag
->type
!= MULTIBOOT_TAG_TYPE_END
;
148 tag
= (struct multiboot_header_tag
*) ((grub_uint32_t
*) tag
+ ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
) / 4))
151 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
:
154 struct multiboot_header_tag_information_request
*request_tag
155 = (struct multiboot_header_tag_information_request
*) tag
;
156 if (request_tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
)
158 for (i
= 0; i
< (request_tag
->size
- sizeof (*request_tag
))
159 / sizeof (request_tag
->requests
[0]); i
++)
160 switch (request_tag
->requests
[i
])
162 case MULTIBOOT_TAG_TYPE_END
:
163 case MULTIBOOT_TAG_TYPE_CMDLINE
:
164 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
:
165 case MULTIBOOT_TAG_TYPE_MODULE
:
166 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
:
167 case MULTIBOOT_TAG_TYPE_BOOTDEV
:
168 case MULTIBOOT_TAG_TYPE_MMAP
:
169 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER
:
170 case MULTIBOOT_TAG_TYPE_VBE
:
171 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS
:
172 case MULTIBOOT_TAG_TYPE_APM
:
173 case MULTIBOOT_TAG_TYPE_EFI32
:
174 case MULTIBOOT_TAG_TYPE_EFI64
:
175 case MULTIBOOT_TAG_TYPE_ACPI_OLD
:
176 case MULTIBOOT_TAG_TYPE_ACPI_NEW
:
177 case MULTIBOOT_TAG_TYPE_NETWORK
:
178 case MULTIBOOT_TAG_TYPE_EFI_MMAP
:
179 case MULTIBOOT_TAG_TYPE_EFI_BS
:
180 case MULTIBOOT_TAG_TYPE_EFI32_IH
:
181 case MULTIBOOT_TAG_TYPE_EFI64_IH
:
182 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR
:
186 grub_free (mld
.buffer
);
187 return grub_error (GRUB_ERR_UNKNOWN_OS
,
188 "unsupported information tag: 0x%x",
189 request_tag
->requests
[i
]);
194 case MULTIBOOT_HEADER_TAG_ADDRESS
:
195 addr_tag
= (struct multiboot_header_tag_address
*) tag
;
198 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
:
200 entry
= ((struct multiboot_header_tag_entry_address
*) tag
)->entry_addr
;
203 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64
:
204 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
205 efi_entry_specified
= 1;
206 efi_entry
= ((struct multiboot_header_tag_entry_address
*) tag
)->entry_addr
;
210 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS
:
211 if (!(((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
212 & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
))
213 accepted_consoles
&= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
;
214 if (((struct multiboot_header_tag_console_flags
*) tag
)->console_flags
215 & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED
)
216 console_required
= 1;
219 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER
:
220 fbtag
= (struct multiboot_header_tag_framebuffer
*) tag
;
221 accepted_consoles
|= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
;
224 case MULTIBOOT_HEADER_TAG_RELOCATABLE
:
226 rel_tag
= (struct multiboot_header_tag_relocatable
*) tag
;
227 mld
.min_addr
= rel_tag
->min_addr
;
228 mld
.max_addr
= rel_tag
->max_addr
;
229 mld
.align
= rel_tag
->align
;
230 switch (rel_tag
->preference
)
232 case MULTIBOOT_LOAD_PREFERENCE_LOW
:
233 mld
.preference
= GRUB_RELOCATOR_PREFERENCE_LOW
;
236 case MULTIBOOT_LOAD_PREFERENCE_HIGH
:
237 mld
.preference
= GRUB_RELOCATOR_PREFERENCE_HIGH
;
241 mld
.preference
= GRUB_RELOCATOR_PREFERENCE_NONE
;
245 /* GRUB always page-aligns modules. */
246 case MULTIBOOT_HEADER_TAG_MODULE_ALIGN
:
249 case MULTIBOOT_HEADER_TAG_EFI_BS
:
250 #ifdef GRUB_MACHINE_EFI
256 if (! (tag
->flags
& MULTIBOOT_HEADER_TAG_OPTIONAL
))
258 grub_free (mld
.buffer
);
259 return grub_error (GRUB_ERR_UNKNOWN_OS
,
260 "unsupported tag: 0x%x", tag
->type
);
265 if (addr_tag
&& !entry_specified
&& !(keep_bs
&& efi_entry_specified
))
267 grub_free (mld
.buffer
);
268 return grub_error (GRUB_ERR_UNKNOWN_OS
,
269 "load address tag without entry address tag");
274 grub_uint64_t load_addr
= (addr_tag
->load_addr
+ 1)
275 ? addr_tag
->load_addr
: (addr_tag
->header_addr
276 - ((char *) header
- (char *) mld
.buffer
));
277 int offset
= ((char *) header
- (char *) mld
.buffer
-
278 (addr_tag
->header_addr
- load_addr
));
279 int load_size
= ((addr_tag
->load_end_addr
== 0) ? file
->size
- offset
:
280 addr_tag
->load_end_addr
- addr_tag
->load_addr
);
281 grub_size_t code_size
;
283 grub_relocator_chunk_t ch
;
285 if (addr_tag
->bss_end_addr
)
286 code_size
= (addr_tag
->bss_end_addr
- load_addr
);
288 code_size
= load_size
;
292 if (code_size
> mld
.max_addr
|| mld
.min_addr
> mld
.max_addr
- code_size
)
294 grub_free (mld
.buffer
);
295 return grub_error (GRUB_ERR_BAD_OS
, "invalid min/max address and/or load size");
298 err
= grub_relocator_alloc_chunk_align (grub_multiboot_relocator
, &ch
,
299 mld
.min_addr
, mld
.max_addr
- code_size
,
300 code_size
, mld
.align
? mld
.align
: 1,
301 mld
.preference
, keep_bs
);
304 err
= grub_relocator_alloc_chunk_addr (grub_multiboot_relocator
,
305 &ch
, load_addr
, code_size
);
308 grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
309 grub_free (mld
.buffer
);
312 mld
.link_base_addr
= load_addr
;
313 mld
.load_base_addr
= get_physical_target_address (ch
);
314 source
= get_virtual_current_address (ch
);
316 grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
317 "load_size=0x%lx, relocatable=%d\n", mld
.link_base_addr
,
318 mld
.load_base_addr
, (long) code_size
, mld
.relocatable
);
321 grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
322 (long) mld
.align
, mld
.preference
, keep_bs
);
324 if ((grub_file_seek (file
, offset
)) == (grub_off_t
) -1)
326 grub_free (mld
.buffer
);
330 grub_file_read (file
, source
, load_size
);
333 grub_free (mld
.buffer
);
337 if (addr_tag
->bss_end_addr
)
338 grub_memset ((grub_uint8_t
*) source
+ load_size
, 0,
339 addr_tag
->bss_end_addr
- load_addr
- load_size
);
344 mld
.filename
= filename
;
345 mld
.avoid_efi_boot_services
= keep_bs
;
346 err
= grub_multiboot_load_elf (&mld
);
349 grub_free (mld
.buffer
);
354 load_base_addr
= mld
.load_base_addr
;
356 if (keep_bs
&& efi_entry_specified
)
357 grub_multiboot_payload_eip
= efi_entry
;
358 else if (entry_specified
)
359 grub_multiboot_payload_eip
= entry
;
364 * Both branches are mathematically equivalent. However, it looks
365 * that real life (C?) is more complicated. I am trying to avoid
366 * wrap around here if mld.load_base_addr < mld.link_base_addr.
367 * If you look at C operator precedence then everything should work.
368 * However, I am not 100% sure that a given compiler will not
369 * optimize/break this stuff. So, maybe we should use signed
372 if (mld
.load_base_addr
>= mld
.link_base_addr
)
373 grub_multiboot_payload_eip
+= mld
.load_base_addr
- mld
.link_base_addr
;
375 grub_multiboot_payload_eip
-= mld
.link_base_addr
- mld
.load_base_addr
;
379 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
,
381 fbtag
->width
, fbtag
->height
,
382 fbtag
->depth
, console_required
);
384 err
= grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
,
386 0, 0, 0, console_required
);
393 #if GRUB_MACHINE_HAS_ACPI
394 struct grub_acpi_rsdp_v20
*p
= grub_acpi_get_rsdpv2 ();
399 return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
400 + p
->length
, MULTIBOOT_TAG_ALIGN
);
406 #ifdef GRUB_MACHINE_EFI
408 static grub_efi_uintn_t efi_mmap_size
= 0;
410 /* Find the optimal number of pages for the memory map. Is it better to
411 move this code to efi/mm.c? */
413 find_efi_mmap_size (void)
415 efi_mmap_size
= (1 << 12);
419 grub_efi_memory_descriptor_t
*mmap
;
420 grub_efi_uintn_t desc_size
;
421 grub_efi_uintn_t cur_mmap_size
= efi_mmap_size
;
423 mmap
= grub_malloc (cur_mmap_size
);
427 ret
= grub_efi_get_memory_map (&cur_mmap_size
, mmap
, 0, &desc_size
, 0);
435 if (efi_mmap_size
< cur_mmap_size
)
436 efi_mmap_size
= cur_mmap_size
;
437 efi_mmap_size
+= (1 << 12);
440 /* Increase the size a bit for safety, because GRUB allocates more on
441 later, and EFI itself may allocate more. */
442 efi_mmap_size
+= (3 << 12);
444 efi_mmap_size
= ALIGN_UP (efi_mmap_size
, 4096);
451 struct grub_net_network_level_interface
*net
;
454 FOR_NET_NETWORK_LEVEL_INTERFACES(net
)
456 ret
+= ALIGN_UP (sizeof (struct multiboot_tag_network
) + net
->dhcp_acklen
,
457 MULTIBOOT_TAG_ALIGN
);
462 grub_multiboot_get_mbi_size (void)
464 #ifdef GRUB_MACHINE_EFI
465 if (!keep_bs
&& !efi_mmap_size
)
466 find_efi_mmap_size ();
468 return 2 * sizeof (grub_uint32_t
) + sizeof (struct multiboot_tag
)
469 + sizeof (struct multiboot_tag
)
470 + (sizeof (struct multiboot_tag_string
)
471 + ALIGN_UP (cmdline_size
, MULTIBOOT_TAG_ALIGN
))
472 + (sizeof (struct multiboot_tag_string
)
473 + ALIGN_UP (sizeof (PACKAGE_STRING
), MULTIBOOT_TAG_ALIGN
))
474 + (modcnt
* sizeof (struct multiboot_tag_module
) + total_modcmd
)
475 + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo
),
477 + ALIGN_UP (sizeof (struct multiboot_tag_bootdev
), MULTIBOOT_TAG_ALIGN
)
478 + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections
), MULTIBOOT_TAG_ALIGN
)
479 + ALIGN_UP (elf_sec_entsize
* elf_sec_num
, MULTIBOOT_TAG_ALIGN
)
480 + ALIGN_UP ((sizeof (struct multiboot_tag_mmap
)
481 + grub_get_multiboot_mmap_count ()
482 * sizeof (struct multiboot_mmap_entry
)), MULTIBOOT_TAG_ALIGN
)
483 + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer
), MULTIBOOT_TAG_ALIGN
)
484 + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi
)
485 + sizeof (struct grub_acpi_rsdp_v10
), MULTIBOOT_TAG_ALIGN
)
486 + ALIGN_UP (sizeof (struct multiboot_tag_load_base_addr
), MULTIBOOT_TAG_ALIGN
)
489 #ifdef GRUB_MACHINE_EFI
490 + ALIGN_UP (sizeof (struct multiboot_tag_efi32
), MULTIBOOT_TAG_ALIGN
)
491 + ALIGN_UP (sizeof (struct multiboot_tag_efi32_ih
), MULTIBOOT_TAG_ALIGN
)
492 + ALIGN_UP (sizeof (struct multiboot_tag_efi64
), MULTIBOOT_TAG_ALIGN
)
493 + ALIGN_UP (sizeof (struct multiboot_tag_efi64_ih
), MULTIBOOT_TAG_ALIGN
)
494 + ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap
)
495 + efi_mmap_size
, MULTIBOOT_TAG_ALIGN
)
497 + sizeof (struct multiboot_tag_vbe
) + MULTIBOOT_TAG_ALIGN
- 1
498 + sizeof (struct multiboot_tag_apm
) + MULTIBOOT_TAG_ALIGN
- 1;
501 /* Helper for grub_fill_multiboot_mmap. */
503 grub_fill_multiboot_mmap_iter (grub_uint64_t addr
, grub_uint64_t size
,
504 grub_memory_type_t type
, void *data
)
506 struct multiboot_mmap_entry
**mmap_entry
= data
;
508 (*mmap_entry
)->addr
= addr
;
509 (*mmap_entry
)->len
= size
;
510 (*mmap_entry
)->type
= type
;
511 (*mmap_entry
)->zero
= 0;
517 /* Fill previously allocated Multiboot mmap. */
519 grub_fill_multiboot_mmap (struct multiboot_tag_mmap
*tag
)
521 struct multiboot_mmap_entry
*mmap_entry
= tag
->entries
;
523 tag
->type
= MULTIBOOT_TAG_TYPE_MMAP
;
524 tag
->size
= sizeof (struct multiboot_tag_mmap
)
525 + sizeof (struct multiboot_mmap_entry
) * grub_get_multiboot_mmap_count ();
526 tag
->entry_size
= sizeof (struct multiboot_mmap_entry
);
527 tag
->entry_version
= 0;
529 grub_mmap_iterate (grub_fill_multiboot_mmap_iter
, &mmap_entry
);
532 #if defined (GRUB_MACHINE_PCBIOS)
534 fill_vbe_tag (struct multiboot_tag_vbe
*tag
)
536 grub_vbe_status_t status
;
537 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
539 tag
->type
= MULTIBOOT_TAG_TYPE_VBE
;
542 status
= grub_vbe_bios_get_controller_info (scratch
);
543 if (status
!= GRUB_VBE_STATUS_OK
)
546 grub_memcpy (&tag
->vbe_control_info
, scratch
,
547 sizeof (struct grub_vbe_info_block
));
549 status
= grub_vbe_bios_get_mode (scratch
);
550 tag
->vbe_mode
= *(grub_uint32_t
*) scratch
;
551 if (status
!= GRUB_VBE_STATUS_OK
)
554 /* get_mode_info isn't available for mode 3. */
555 if (tag
->vbe_mode
== 3)
557 struct grub_vbe_mode_info_block
*mode_info
= (void *) &tag
->vbe_mode_info
;
558 grub_memset (mode_info
, 0,
559 sizeof (struct grub_vbe_mode_info_block
));
560 mode_info
->memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
561 mode_info
->x_resolution
= 80;
562 mode_info
->y_resolution
= 25;
566 status
= grub_vbe_bios_get_mode_info (tag
->vbe_mode
, scratch
);
567 if (status
!= GRUB_VBE_STATUS_OK
)
569 grub_memcpy (&tag
->vbe_mode_info
, scratch
,
570 sizeof (struct grub_vbe_mode_info_block
));
572 grub_vbe_bios_get_pm_interface (&tag
->vbe_interface_seg
,
573 &tag
->vbe_interface_off
,
574 &tag
->vbe_interface_len
);
576 tag
->size
= sizeof (*tag
);
581 retrieve_video_parameters (grub_properly_aligned_t
**ptrorig
)
584 struct grub_video_mode_info mode_info
;
586 grub_video_driver_id_t driv_id
;
587 struct grub_video_palette_data palette
[256];
588 struct multiboot_tag_framebuffer
*tag
589 = (struct multiboot_tag_framebuffer
*) *ptrorig
;
591 err
= grub_multiboot_set_video_mode ();
595 grub_errno
= GRUB_ERR_NONE
;
598 grub_video_get_palette (0, ARRAY_SIZE (palette
), palette
);
600 driv_id
= grub_video_get_driver_id ();
602 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
604 struct grub_vbe_mode_info_block vbe_mode_info
;
605 grub_uint32_t vbe_mode
;
607 #if defined (GRUB_MACHINE_PCBIOS)
609 grub_vbe_status_t status
;
610 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
611 status
= grub_vbe_bios_get_mode (scratch
);
612 vbe_mode
= *(grub_uint32_t
*) scratch
;
613 if (status
!= GRUB_VBE_STATUS_OK
)
614 return GRUB_ERR_NONE
;
620 /* get_mode_info isn't available for mode 3. */
623 grub_memset (&vbe_mode_info
, 0,
624 sizeof (struct grub_vbe_mode_info_block
));
625 vbe_mode_info
.memory_model
= GRUB_VBE_MEMORY_MODEL_TEXT
;
626 vbe_mode_info
.x_resolution
= 80;
627 vbe_mode_info
.y_resolution
= 25;
629 #if defined (GRUB_MACHINE_PCBIOS)
632 grub_vbe_status_t status
;
633 void *scratch
= (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
634 status
= grub_vbe_bios_get_mode_info (vbe_mode
, scratch
);
635 if (status
!= GRUB_VBE_STATUS_OK
)
636 return GRUB_ERR_NONE
;
637 grub_memcpy (&vbe_mode_info
, scratch
,
638 sizeof (struct grub_vbe_mode_info_block
));
642 if (vbe_mode_info
.memory_model
== GRUB_VBE_MEMORY_MODEL_TEXT
)
644 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
645 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
646 tag
->common
.size
= 0;
648 tag
->common
.framebuffer_addr
= 0xb8000;
650 tag
->common
.framebuffer_pitch
= 2 * vbe_mode_info
.x_resolution
;
651 tag
->common
.framebuffer_width
= vbe_mode_info
.x_resolution
;
652 tag
->common
.framebuffer_height
= vbe_mode_info
.y_resolution
;
654 tag
->common
.framebuffer_bpp
= 16;
656 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT
;
657 tag
->common
.size
= sizeof (tag
->common
);
658 tag
->common
.reserved
= 0;
659 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
660 / sizeof (grub_properly_aligned_t
);
662 return GRUB_ERR_NONE
;
665 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
666 return GRUB_ERR_NONE
;
669 #if GRUB_MACHINE_HAS_VBE
671 struct multiboot_tag_vbe
*tag_vbe
= (struct multiboot_tag_vbe
*) *ptrorig
;
673 fill_vbe_tag (tag_vbe
);
675 *ptrorig
+= ALIGN_UP (tag_vbe
->size
, MULTIBOOT_TAG_ALIGN
)
676 / sizeof (grub_properly_aligned_t
);
680 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
684 tag
= (struct multiboot_tag_framebuffer
*) *ptrorig
;
685 tag
->common
.type
= MULTIBOOT_TAG_TYPE_FRAMEBUFFER
;
686 tag
->common
.size
= 0;
688 tag
->common
.framebuffer_addr
= (grub_addr_t
) framebuffer
;
689 tag
->common
.framebuffer_pitch
= mode_info
.pitch
;
691 tag
->common
.framebuffer_width
= mode_info
.width
;
692 tag
->common
.framebuffer_height
= mode_info
.height
;
694 tag
->common
.framebuffer_bpp
= mode_info
.bpp
;
696 tag
->common
.reserved
= 0;
698 if (mode_info
.mode_type
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
)
701 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED
;
702 tag
->framebuffer_palette_num_colors
= mode_info
.number_of_colors
;
703 if (tag
->framebuffer_palette_num_colors
> ARRAY_SIZE (palette
))
704 tag
->framebuffer_palette_num_colors
= ARRAY_SIZE (palette
);
705 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
)
706 + sizeof (multiboot_uint16_t
) + tag
->framebuffer_palette_num_colors
707 * sizeof (struct multiboot_color
);
708 for (i
= 0; i
< tag
->framebuffer_palette_num_colors
; i
++)
710 tag
->framebuffer_palette
[i
].red
= palette
[i
].r
;
711 tag
->framebuffer_palette
[i
].green
= palette
[i
].g
;
712 tag
->framebuffer_palette
[i
].blue
= palette
[i
].b
;
717 tag
->common
.framebuffer_type
= MULTIBOOT_FRAMEBUFFER_TYPE_RGB
;
718 tag
->framebuffer_red_field_position
= mode_info
.red_field_pos
;
719 tag
->framebuffer_red_mask_size
= mode_info
.red_mask_size
;
720 tag
->framebuffer_green_field_position
= mode_info
.green_field_pos
;
721 tag
->framebuffer_green_mask_size
= mode_info
.green_mask_size
;
722 tag
->framebuffer_blue_field_position
= mode_info
.blue_field_pos
;
723 tag
->framebuffer_blue_mask_size
= mode_info
.blue_mask_size
;
725 tag
->common
.size
= sizeof (struct multiboot_tag_framebuffer_common
) + 6;
727 *ptrorig
+= ALIGN_UP (tag
->common
.size
, MULTIBOOT_TAG_ALIGN
)
728 / sizeof (grub_properly_aligned_t
);
730 return GRUB_ERR_NONE
;
734 grub_multiboot_make_mbi (grub_uint32_t
*target
)
736 grub_properly_aligned_t
*ptrorig
;
737 grub_properly_aligned_t
*mbistart
;
740 grub_relocator_chunk_t ch
;
742 bufsize
= grub_multiboot_get_mbi_size ();
744 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
% sizeof (grub_properly_aligned_t
) == 0);
746 err
= grub_relocator_alloc_chunk_align (grub_multiboot_relocator
, &ch
,
747 0, 0xffffffff - bufsize
,
748 bufsize
, MULTIBOOT_TAG_ALIGN
,
749 GRUB_RELOCATOR_PREFERENCE_NONE
, 1);
753 ptrorig
= get_virtual_current_address (ch
);
754 #if defined (__i386__) || defined (__x86_64__)
755 *target
= get_physical_target_address (ch
);
756 #elif defined (__mips)
757 *target
= get_physical_target_address (ch
) | 0x80000000;
759 #error Please complete this
763 COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t
))
764 % sizeof (grub_properly_aligned_t
) == 0);
765 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
766 % sizeof (grub_properly_aligned_t
) == 0);
767 ptrorig
+= (2 * sizeof (grub_uint32_t
)) / sizeof (grub_properly_aligned_t
);
770 struct multiboot_tag_load_base_addr
*tag
= (struct multiboot_tag_load_base_addr
*) ptrorig
;
771 tag
->type
= MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR
;
772 tag
->size
= sizeof (struct multiboot_tag_load_base_addr
);
773 tag
->load_base_addr
= load_base_addr
;
774 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
775 / sizeof (grub_properly_aligned_t
);
779 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
780 tag
->type
= MULTIBOOT_TAG_TYPE_CMDLINE
;
781 tag
->size
= sizeof (struct multiboot_tag_string
) + cmdline_size
;
782 grub_memcpy (tag
->string
, cmdline
, cmdline_size
);
783 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
784 / sizeof (grub_properly_aligned_t
);
788 struct multiboot_tag_string
*tag
= (struct multiboot_tag_string
*) ptrorig
;
789 tag
->type
= MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME
;
790 tag
->size
= sizeof (struct multiboot_tag_string
) + sizeof (PACKAGE_STRING
);
791 grub_memcpy (tag
->string
, PACKAGE_STRING
, sizeof (PACKAGE_STRING
));
792 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
793 / sizeof (grub_properly_aligned_t
);
796 #ifdef GRUB_MACHINE_PCBIOS
798 struct grub_apm_info info
;
799 if (grub_apm_get_info (&info
))
801 struct multiboot_tag_apm
*tag
= (struct multiboot_tag_apm
*) ptrorig
;
803 tag
->type
= MULTIBOOT_TAG_TYPE_APM
;
804 tag
->size
= sizeof (struct multiboot_tag_apm
);
806 tag
->cseg
= info
.cseg
;
807 tag
->offset
= info
.offset
;
808 tag
->cseg_16
= info
.cseg_16
;
809 tag
->dseg
= info
.dseg
;
810 tag
->flags
= info
.flags
;
811 tag
->cseg_len
= info
.cseg_len
;
812 tag
->dseg_len
= info
.dseg_len
;
813 tag
->cseg_16_len
= info
.cseg_16_len
;
814 tag
->version
= info
.version
;
816 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
817 / sizeof (grub_properly_aligned_t
);
826 for (i
= 0, cur
= modules
; i
< modcnt
; i
++, cur
= cur
->next
)
828 struct multiboot_tag_module
*tag
829 = (struct multiboot_tag_module
*) ptrorig
;
830 tag
->type
= MULTIBOOT_TAG_TYPE_MODULE
;
831 tag
->size
= sizeof (struct multiboot_tag_module
) + cur
->cmdline_size
;
832 tag
->mod_start
= cur
->start
;
833 tag
->mod_end
= tag
->mod_start
+ cur
->size
;
834 grub_memcpy (tag
->cmdline
, cur
->cmdline
, cur
->cmdline_size
);
835 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
836 / sizeof (grub_properly_aligned_t
);
842 struct multiboot_tag_mmap
*tag
= (struct multiboot_tag_mmap
*) ptrorig
;
843 grub_fill_multiboot_mmap (tag
);
844 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
845 / sizeof (grub_properly_aligned_t
);
849 struct multiboot_tag_elf_sections
*tag
850 = (struct multiboot_tag_elf_sections
*) ptrorig
;
851 tag
->type
= MULTIBOOT_TAG_TYPE_ELF_SECTIONS
;
852 tag
->size
= sizeof (struct multiboot_tag_elf_sections
)
853 + elf_sec_entsize
* elf_sec_num
;
854 grub_memcpy (tag
->sections
, elf_sections
, elf_sec_entsize
* elf_sec_num
);
855 tag
->num
= elf_sec_num
;
856 tag
->entsize
= elf_sec_entsize
;
857 tag
->shndx
= elf_sec_shstrndx
;
858 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
859 / sizeof (grub_properly_aligned_t
);
864 struct multiboot_tag_basic_meminfo
*tag
865 = (struct multiboot_tag_basic_meminfo
*) ptrorig
;
866 tag
->type
= MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
;
867 tag
->size
= sizeof (struct multiboot_tag_basic_meminfo
);
869 /* Convert from bytes to kilobytes. */
870 tag
->mem_lower
= grub_mmap_get_lower () / 1024;
871 tag
->mem_upper
= grub_mmap_get_upper () / 1024;
872 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
873 / sizeof (grub_properly_aligned_t
);
877 struct grub_net_network_level_interface
*net
;
879 FOR_NET_NETWORK_LEVEL_INTERFACES(net
)
882 struct multiboot_tag_network
*tag
883 = (struct multiboot_tag_network
*) ptrorig
;
884 tag
->type
= MULTIBOOT_TAG_TYPE_NETWORK
;
885 tag
->size
= sizeof (struct multiboot_tag_network
) + net
->dhcp_acklen
;
886 grub_memcpy (tag
->dhcpack
, net
->dhcp_ack
, net
->dhcp_acklen
);
887 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
888 / sizeof (grub_properly_aligned_t
);
894 struct multiboot_tag_bootdev
*tag
895 = (struct multiboot_tag_bootdev
*) ptrorig
;
896 tag
->type
= MULTIBOOT_TAG_TYPE_BOOTDEV
;
897 tag
->size
= sizeof (struct multiboot_tag_bootdev
);
899 tag
->biosdev
= biosdev
;
902 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
903 / sizeof (grub_properly_aligned_t
);
907 err
= retrieve_video_parameters (&ptrorig
);
911 grub_errno
= GRUB_ERR_NONE
;
915 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
917 struct multiboot_tag_efi64
*tag
= (struct multiboot_tag_efi64
*) ptrorig
;
918 tag
->type
= MULTIBOOT_TAG_TYPE_EFI64
;
919 tag
->size
= sizeof (*tag
);
920 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
921 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
922 / sizeof (grub_properly_aligned_t
);
926 #if defined (GRUB_MACHINE_EFI) && defined (__i386__)
928 struct multiboot_tag_efi32
*tag
= (struct multiboot_tag_efi32
*) ptrorig
;
929 tag
->type
= MULTIBOOT_TAG_TYPE_EFI32
;
930 tag
->size
= sizeof (*tag
);
931 tag
->pointer
= (grub_addr_t
) grub_efi_system_table
;
932 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
933 / sizeof (grub_properly_aligned_t
);
937 #if GRUB_MACHINE_HAS_ACPI
939 struct multiboot_tag_old_acpi
*tag
= (struct multiboot_tag_old_acpi
*)
941 struct grub_acpi_rsdp_v10
*a
= grub_acpi_get_rsdpv1 ();
944 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_OLD
;
945 tag
->size
= sizeof (*tag
) + sizeof (*a
);
946 grub_memcpy (tag
->rsdp
, a
, sizeof (*a
));
947 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
948 / sizeof (grub_properly_aligned_t
);
953 struct multiboot_tag_new_acpi
*tag
= (struct multiboot_tag_new_acpi
*)
955 struct grub_acpi_rsdp_v20
*a
= grub_acpi_get_rsdpv2 ();
958 tag
->type
= MULTIBOOT_TAG_TYPE_ACPI_NEW
;
959 tag
->size
= sizeof (*tag
) + a
->length
;
960 grub_memcpy (tag
->rsdp
, a
, a
->length
);
961 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
962 / sizeof (grub_properly_aligned_t
);
967 #ifdef GRUB_MACHINE_EFI
969 struct multiboot_tag_efi_mmap
*tag
= (struct multiboot_tag_efi_mmap
*) ptrorig
;
970 grub_efi_uintn_t efi_desc_size
;
971 grub_efi_uint32_t efi_desc_version
;
975 tag
->type
= MULTIBOOT_TAG_TYPE_EFI_MMAP
;
976 tag
->size
= sizeof (*tag
) + efi_mmap_size
;
978 err
= grub_efi_finish_boot_services (&efi_mmap_size
, tag
->efi_mmap
, NULL
,
979 &efi_desc_size
, &efi_desc_version
);
984 tag
->descr_size
= efi_desc_size
;
985 tag
->descr_vers
= efi_desc_version
;
986 tag
->size
= sizeof (*tag
) + efi_mmap_size
;
988 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
989 / sizeof (grub_properly_aligned_t
);
996 struct multiboot_tag
*tag
= (struct multiboot_tag
*) ptrorig
;
997 tag
->type
= MULTIBOOT_TAG_TYPE_EFI_BS
;
998 tag
->size
= sizeof (struct multiboot_tag
);
999 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
1000 / sizeof (grub_properly_aligned_t
);
1005 struct multiboot_tag_efi32_ih
*tag
= (struct multiboot_tag_efi32_ih
*) ptrorig
;
1006 tag
->type
= MULTIBOOT_TAG_TYPE_EFI32_IH
;
1007 tag
->size
= sizeof (struct multiboot_tag_efi32_ih
);
1008 tag
->pointer
= (grub_addr_t
) grub_efi_image_handle
;
1009 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
1010 / sizeof (grub_properly_aligned_t
);
1016 struct multiboot_tag_efi64_ih
*tag
= (struct multiboot_tag_efi64_ih
*) ptrorig
;
1017 tag
->type
= MULTIBOOT_TAG_TYPE_EFI64_IH
;
1018 tag
->size
= sizeof (struct multiboot_tag_efi64_ih
);
1019 tag
->pointer
= (grub_addr_t
) grub_efi_image_handle
;
1020 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
1021 / sizeof (grub_properly_aligned_t
);
1028 struct multiboot_tag
*tag
= (struct multiboot_tag
*) ptrorig
;
1029 tag
->type
= MULTIBOOT_TAG_TYPE_END
;
1030 tag
->size
= sizeof (struct multiboot_tag
);
1031 ptrorig
+= ALIGN_UP (tag
->size
, MULTIBOOT_TAG_ALIGN
)
1032 / sizeof (grub_properly_aligned_t
);
1035 ((grub_uint32_t
*) mbistart
)[0] = (char *) ptrorig
- (char *) mbistart
;
1036 ((grub_uint32_t
*) mbistart
)[1] = 0;
1038 return GRUB_ERR_NONE
;
1042 grub_multiboot_free_mbi (void)
1044 struct module
*cur
, *next
;
1049 grub_free (cmdline
);
1053 for (cur
= modules
; cur
; cur
= next
)
1056 grub_free (cur
->cmdline
);
1060 modules_last
= NULL
;
1064 grub_multiboot_init_mbi (int argc
, char *argv
[])
1066 grub_ssize_t len
= 0;
1068 grub_multiboot_free_mbi ();
1070 len
= grub_loader_cmdline_size (argc
, argv
);
1072 cmdline
= grub_malloc (len
);
1077 grub_create_loader_cmdline (argc
, argv
, cmdline
,
1080 return GRUB_ERR_NONE
;
1084 grub_multiboot_add_module (grub_addr_t start
, grub_size_t size
,
1085 int argc
, char *argv
[])
1087 struct module
*newmod
;
1088 grub_size_t len
= 0;
1090 newmod
= grub_malloc (sizeof (*newmod
));
1093 newmod
->start
= start
;
1094 newmod
->size
= size
;
1096 len
= grub_loader_cmdline_size (argc
, argv
);
1098 newmod
->cmdline
= grub_malloc (len
);
1099 if (! newmod
->cmdline
)
1104 newmod
->cmdline_size
= len
;
1105 total_modcmd
+= ALIGN_UP (len
, MULTIBOOT_TAG_ALIGN
);
1107 grub_create_loader_cmdline (argc
, argv
, newmod
->cmdline
,
1108 newmod
->cmdline_size
);
1111 modules_last
->next
= newmod
;
1114 modules_last
= newmod
;
1118 return GRUB_ERR_NONE
;
1122 grub_multiboot_set_bootdev (void)
1129 #ifdef GRUB_MACHINE_PCBIOS
1130 biosdev
= grub_get_root_biosnumber ();
1132 biosdev
= 0xffffffff;
1135 if (biosdev
== 0xffffffff)
1138 dev
= grub_device_open (0);
1139 if (dev
&& dev
->disk
&& dev
->disk
->partition
)
1141 if (dev
->disk
->partition
->parent
)
1143 part
= dev
->disk
->partition
->number
;
1144 slice
= dev
->disk
->partition
->parent
->number
;
1147 slice
= dev
->disk
->partition
->number
;
1150 grub_device_close (dev
);