1 /* multiboot.c - boot a multiboot OS image. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 * FIXME: The following features from the Multiboot specification still
22 * need to be implemented:
26 * - ROM configuration table
30 #include <grub/loader.h>
31 #include <grub/command.h>
32 #include <grub/machine/loader.h>
33 #include <grub/multiboot.h>
34 #include <grub/cpu/multiboot.h>
36 #include <grub/aout.h>
37 #include <grub/file.h>
41 #include <grub/misc.h>
42 #include <grub/gzio.h>
44 #include <grub/cpu/relocator.h>
45 #include <grub/video.h>
46 #include <grub/memory.h>
47 #include <grub/i18n.h>
49 #ifdef GRUB_MACHINE_EFI
50 #include <grub/efi/efi.h>
53 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
54 #define DEFAULT_VIDEO_MODE "text"
56 #define DEFAULT_VIDEO_MODE "auto"
59 grub_size_t grub_multiboot_alloc_mbi
;
61 char *grub_multiboot_payload_orig
;
62 grub_addr_t grub_multiboot_payload_dest
;
63 grub_size_t grub_multiboot_pure_size
;
64 grub_uint32_t grub_multiboot_payload_eip
;
65 static int accepts_video
;
66 static int accepts_ega_text
;
67 static int console_required
;
68 static grub_dl_t my_mod
;
71 /* Return the length of the Multiboot mmap that will be needed to allocate
72 our platform's map. */
74 grub_get_multiboot_mmap_count (void)
76 grub_size_t count
= 0;
78 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
79 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
__attribute__ ((unused
)),
80 grub_uint64_t size
__attribute__ ((unused
)),
81 grub_uint32_t type
__attribute__ ((unused
)))
87 grub_mmap_iterate (hook
);
93 grub_multiboot_set_video_mode (void)
98 if (accepts_video
|| !GRUB_MACHINE_HAS_VGA_TEXT
)
100 modevar
= grub_env_get ("gfxpayload");
101 if (! modevar
|| *modevar
== 0)
102 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
, 0, 0);
106 tmp
= grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE
, modevar
);
109 err
= grub_video_set_mode (tmp
, 0, 0);
114 err
= grub_video_set_mode ("text", 0, 0);
120 grub_multiboot_boot (void)
122 grub_size_t mbi_size
;
124 struct grub_relocator32_state state
= MULTIBOOT_INITIAL_STATE
;
126 state
.MULTIBOOT_ENTRY_REGISTER
= grub_multiboot_payload_eip
;
128 mbi_size
= grub_multiboot_get_mbi_size ();
129 if (grub_multiboot_alloc_mbi
< mbi_size
)
131 grub_multiboot_payload_orig
132 = grub_relocator32_realloc (grub_multiboot_payload_orig
,
133 grub_multiboot_pure_size
+ mbi_size
);
134 if (!grub_multiboot_payload_orig
)
136 grub_multiboot_alloc_mbi
= mbi_size
;
139 state
.MULTIBOOT_MBI_REGISTER
= grub_multiboot_payload_dest
140 + grub_multiboot_pure_size
;
141 err
= grub_multiboot_make_mbi (grub_multiboot_payload_orig
,
142 grub_multiboot_payload_dest
,
143 grub_multiboot_pure_size
, mbi_size
);
147 #ifdef GRUB_MACHINE_EFI
148 if (! grub_efi_finish_boot_services ())
149 grub_fatal ("cannot exit boot services");
152 grub_relocator32_boot (grub_multiboot_payload_orig
,
153 grub_multiboot_payload_dest
,
157 return GRUB_ERR_NONE
;
161 grub_multiboot_unload (void)
163 grub_multiboot_free_mbi ();
165 grub_relocator32_free (grub_multiboot_payload_orig
);
167 grub_multiboot_alloc_mbi
= 0;
169 grub_multiboot_payload_orig
= NULL
;
170 grub_dl_unref (my_mod
);
172 return GRUB_ERR_NONE
;
175 #define MULTIBOOT_LOAD_ELF64
176 #include "multiboot_elfxx.c"
177 #undef MULTIBOOT_LOAD_ELF64
179 #define MULTIBOOT_LOAD_ELF32
180 #include "multiboot_elfxx.c"
181 #undef MULTIBOOT_LOAD_ELF32
183 /* Load ELF32 or ELF64. */
185 grub_multiboot_load_elf (grub_file_t file
, void *buffer
)
187 if (grub_multiboot_is_elf32 (buffer
))
188 return grub_multiboot_load_elf32 (file
, buffer
);
189 else if (grub_multiboot_is_elf64 (buffer
))
190 return grub_multiboot_load_elf64 (file
, buffer
);
192 return grub_error (GRUB_ERR_UNKNOWN_OS
, "unknown ELF class");
196 grub_multiboot_set_console (int console_type
, int accepted_consoles
,
197 int width
, int height
, int depth
,
200 console_required
= console_req
;
201 if (!(accepted_consoles
202 & (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
203 | (GRUB_MACHINE_HAS_VGA_TEXT
? GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
: 0))))
205 if (console_required
)
206 return grub_error (GRUB_ERR_BAD_OS
,
207 "OS requires a console but none is available");
208 grub_printf ("WARNING: no console will be available to OS");
210 accepts_ega_text
= 0;
211 return GRUB_ERR_NONE
;
214 if (console_type
== GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
)
217 if (depth
&& width
&& height
)
218 buf
= grub_xasprintf ("%dx%dx%d,%dx%d,auto", width
,
219 height
, depth
, width
, height
);
220 else if (width
&& height
)
221 buf
= grub_xasprintf ("%dx%d,auto", width
, height
);
223 buf
= grub_strdup ("auto");
227 grub_env_set ("gfxpayload", buf
);
231 grub_env_set ("gfxpayload", "text");
233 accepts_video
= !!(accepted_consoles
& GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
);
234 accepts_ega_text
= !!(accepted_consoles
& GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
);
235 return GRUB_ERR_NONE
;
239 grub_cmd_multiboot (grub_command_t cmd
__attribute__ ((unused
)),
240 int argc
, char *argv
[])
242 grub_file_t file
= 0;
245 grub_loader_unset ();
248 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no kernel specified");
250 file
= grub_gzfile_open (argv
[0], 1);
252 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "couldn't open file");
254 grub_dl_ref (my_mod
);
257 grub_multiboot_init_mbi (argc
- 1, argv
+ 1);
259 grub_relocator32_free (grub_multiboot_payload_orig
);
260 grub_multiboot_payload_orig
= NULL
;
262 err
= grub_multiboot_load (file
);
266 grub_multiboot_set_bootdev ();
268 grub_loader_set (grub_multiboot_boot
, grub_multiboot_unload
, 0);
272 grub_file_close (file
);
274 if (grub_errno
!= GRUB_ERR_NONE
)
276 grub_relocator32_free (grub_multiboot_payload_orig
);
277 grub_multiboot_free_mbi ();
278 grub_dl_unref (my_mod
);
285 grub_cmd_module (grub_command_t cmd
__attribute__ ((unused
)),
286 int argc
, char *argv
[])
288 grub_file_t file
= 0;
294 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no module specified");
296 if (!grub_multiboot_payload_orig
)
297 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
298 "you need to load the multiboot kernel first");
300 file
= grub_gzfile_open (argv
[0], 1);
304 size
= grub_file_size (file
);
305 module
= grub_memalign (MULTIBOOT_MOD_ALIGN
, size
);
308 grub_file_close (file
);
312 err
= grub_multiboot_add_module ((grub_addr_t
) module
, size
,
316 grub_file_close (file
);
320 if (grub_file_read (file
, module
, size
) != size
)
322 grub_file_close (file
);
323 return grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
326 grub_file_close (file
);
327 return GRUB_ERR_NONE
;;
330 static grub_command_t cmd_multiboot
, cmd_module
;
332 GRUB_MOD_INIT(multiboot
)
335 #ifdef GRUB_USE_MULTIBOOT2
336 grub_register_command ("multiboot2", grub_cmd_multiboot
,
337 0, N_("Load a multiboot 2 kernel."));
339 grub_register_command ("module2", grub_cmd_module
,
340 0, N_("Load a multiboot 2 module."));
342 grub_register_command ("multiboot", grub_cmd_multiboot
,
343 0, N_("Load a multiboot kernel."));
345 grub_register_command ("module", grub_cmd_module
,
346 0, N_("Load a multiboot module."));
352 GRUB_MOD_FINI(multiboot
)
354 grub_unregister_command (cmd_multiboot
);
355 grub_unregister_command (cmd_module
);