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);