]>
Commit | Line | Data |
---|---|---|
bc8b32b3 | 1 | /* multiboot_loader.c - boot multiboot kernel image */ |
e5dfe777 | 2 | /* |
3 | * GRUB -- GRand Unified Bootloader | |
bc8b32b3 | 4 | * Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc. |
e5dfe777 | 5 | * |
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. | |
10 | * | |
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. | |
15 | * | |
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/>. | |
18 | */ | |
19 | ||
e5dfe777 | 20 | #include <grub/multiboot.h> |
e5dfe777 | 21 | #include <grub/elf.h> |
22 | #include <grub/file.h> | |
23 | #include <grub/err.h> | |
e5dfe777 | 24 | #include <grub/dl.h> |
25 | #include <grub/mm.h> | |
26 | #include <grub/misc.h> | |
27 | #include <grub/gzio.h> | |
b1b797cb | 28 | #include <grub/command.h> |
809bbfeb | 29 | #include <grub/i18n.h> |
e5dfe777 | 30 | |
31 | grub_dl_t my_mod; | |
32 | ||
e5dfe777 | 33 | static int |
34 | find_multi_boot1_header (grub_file_t file) | |
35 | { | |
8d0edf4a | 36 | struct multiboot_header *header; |
e5dfe777 | 37 | char buffer[MULTIBOOT_SEARCH]; |
38 | int found_status = 0; | |
39 | grub_ssize_t len; | |
b39f9d20 | 40 | |
e5dfe777 | 41 | len = grub_file_read (file, buffer, MULTIBOOT_SEARCH); |
42 | if (len < 32) | |
43 | return found_status; | |
44 | ||
45 | /* Look for the multiboot header in the buffer. The header should | |
46 | be at least 12 bytes and aligned on a 4-byte boundary. */ | |
8d0edf4a | 47 | for (header = (struct multiboot_header *) buffer; |
e5dfe777 | 48 | ((char *) header <= buffer + len - 12) || (header = 0); |
8d0edf4a | 49 | header = (struct multiboot_header *) ((char *) header + 4)) |
e5dfe777 | 50 | { |
e4d47d8d | 51 | if (header->magic == MULTIBOOT_HEADER_MAGIC |
e5dfe777 | 52 | && !(header->magic + header->flags + header->checksum)) |
53 | { | |
54 | found_status = 1; | |
55 | break; | |
56 | } | |
57 | } | |
58 | ||
59 | return found_status; | |
60 | } | |
61 | ||
b1b797cb | 62 | static grub_err_t |
63 | grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)), | |
64 | int argc, char *argv[]) | |
e5dfe777 | 65 | { |
e5dfe777 | 66 | grub_file_t file = 0; |
67 | int header_multi_ver_found = 0; | |
68 | ||
69 | grub_dl_ref (my_mod); | |
70 | ||
71 | if (argc == 0) | |
72 | { | |
7fd0baee | 73 | grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); |
e5dfe777 | 74 | goto fail; |
75 | } | |
76 | ||
77 | file = grub_gzfile_open (argv[0], 1); | |
78 | if (! file) | |
79 | { | |
7fd0baee | 80 | grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file"); |
e5dfe777 | 81 | goto fail; |
82 | } | |
83 | ||
84 | /* find which header is in the file */ | |
c32ee8c9 | 85 | if (find_multi_boot1_header (file)) |
e5dfe777 | 86 | header_multi_ver_found = 1; |
87 | else | |
88 | { | |
7fd0baee | 89 | grub_error (GRUB_ERR_BAD_OS, "multiboot header not found"); |
c32ee8c9 | 90 | goto fail; |
e5dfe777 | 91 | } |
92 | ||
1bc09c35 | 93 | /* close file before calling functions */ |
94 | if (file) | |
95 | grub_file_close (file); | |
e5dfe777 | 96 | |
1bc09c35 | 97 | /* Launch multi boot with header */ |
e5dfe777 | 98 | |
bc8b32b3 RM |
99 | grub_dprintf ("multiboot_loader", |
100 | "Launching multiboot 1 grub_multiboot() function\n"); | |
101 | grub_multiboot (argc, argv); | |
e5dfe777 | 102 | |
1bc09c35 | 103 | return grub_errno; |
e5dfe777 | 104 | |
105 | fail: | |
106 | if (file) | |
1bc09c35 | 107 | grub_file_close (file); |
e5dfe777 | 108 | |
109 | grub_dl_unref (my_mod); | |
b1b797cb | 110 | |
111 | return grub_errno; | |
e5dfe777 | 112 | } |
113 | ||
b1b797cb | 114 | static grub_err_t |
115 | grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)), | |
116 | int argc, char *argv[]) | |
e5dfe777 | 117 | { |
118 | ||
bc8b32b3 RM |
119 | grub_dprintf("multiboot_loader", |
120 | "Launching multiboot 1 grub_module() function\n"); | |
121 | grub_module (argc, argv); | |
b1b797cb | 122 | |
123 | return grub_errno; | |
e5dfe777 | 124 | } |
125 | ||
b1b797cb | 126 | static grub_command_t cmd_multiboot, cmd_module; |
127 | ||
e5dfe777 | 128 | GRUB_MOD_INIT(multiboot) |
129 | { | |
b1b797cb | 130 | cmd_multiboot = |
bc8b32b3 RM |
131 | #ifdef GRUB_USE_MULTIBOOT2 |
132 | grub_register_command ("multiboot2", grub_cmd_multiboot_loader, | |
809bbfeb | 133 | 0, N_("Load a multiboot 2 kernel.")); |
bc8b32b3 | 134 | #else |
b1b797cb | 135 | grub_register_command ("multiboot", grub_cmd_multiboot_loader, |
809bbfeb | 136 | 0, N_("Load a multiboot kernel.")); |
bc8b32b3 RM |
137 | #endif |
138 | ||
b1b797cb | 139 | cmd_module = |
140 | grub_register_command ("module", grub_cmd_module_loader, | |
809bbfeb | 141 | 0, N_("Load a multiboot module.")); |
e5dfe777 | 142 | |
143 | my_mod = mod; | |
144 | } | |
145 | ||
146 | GRUB_MOD_FINI(multiboot) | |
147 | { | |
b1b797cb | 148 | grub_unregister_command (cmd_multiboot); |
149 | grub_unregister_command (cmd_module); | |
e5dfe777 | 150 | } |