]>
Commit | Line | Data |
---|---|---|
4b13b216 | 1 | /* grub-setup.c - make GRUB usable */ |
1cc73a62 | 2 | /* |
4b13b216 | 3 | * GRUB -- GRand Unified Bootloader |
a98f4a08 | 4 | * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. |
1cc73a62 | 5 | * |
5a79f472 | 6 | * GRUB is free software: you can redistribute it and/or modify |
1cc73a62 | 7 | * it under the terms of the GNU General Public License as published by |
5a79f472 | 8 | * the Free Software Foundation, either version 3 of the License, or |
1cc73a62 | 9 | * (at your option) any later version. |
10 | * | |
5a79f472 | 11 | * GRUB is distributed in the hope that it will be useful, |
1cc73a62 | 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 | |
5a79f472 | 17 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
1cc73a62 | 18 | */ |
19 | ||
20 | #include <config.h> | |
c06c7520 VS |
21 | |
22 | #define _GNU_SOURCE 1 | |
23 | ||
24 | #include <string.h> | |
25 | ||
4b13b216 | 26 | #include <grub/types.h> |
8c411768 | 27 | #include <grub/emu/misc.h> |
4b13b216 | 28 | #include <grub/util/misc.h> |
29 | #include <grub/device.h> | |
30 | #include <grub/disk.h> | |
31 | #include <grub/file.h> | |
32 | #include <grub/fs.h> | |
3f1578fe | 33 | #include <grub/partition.h> |
5f968e1e | 34 | #include <grub/env.h> |
8c411768 | 35 | #include <grub/emu/hostdisk.h> |
9cacaa17 | 36 | #include <grub/term.h> |
f577f7a0 | 37 | #include <grub/i18n.h> |
c06c7520 | 38 | #include <grub/crypto.h> |
d2ea4551 | 39 | #include <grub/emu/getroot.h> |
c06c7520 | 40 | #include <grub/util/install.h> |
e1e49678 | 41 | |
ca3e2088 VS |
42 | #pragma GCC diagnostic ignored "-Wmissing-prototypes" |
43 | #pragma GCC diagnostic ignored "-Wmissing-declarations" | |
c5930ec8 | 44 | #include <argp.h> |
ca3e2088 VS |
45 | #pragma GCC diagnostic error "-Wmissing-prototypes" |
46 | #pragma GCC diagnostic error "-Wmissing-declarations" | |
1cc73a62 | 47 | |
d2ea4551 VS |
48 | /* On SPARC this program fills in various fields inside of the 'boot' and 'core' |
49 | * image files. | |
50 | * | |
51 | * The 'boot' image needs to know the OBP path name of the root | |
52 | * device. It also needs to know the initial block number of | |
53 | * 'core' (which is 'diskboot' concatenated with 'kernel' and | |
54 | * all the modules, this is created by grub-mkimage). This resulting | |
55 | * 'boot' image is 512 bytes in size and is placed in the second block | |
56 | * of a partition. | |
57 | * | |
58 | * The initial 'diskboot' block acts as a loader for the actual GRUB | |
59 | * kernel. It contains the loading code and then a block list. | |
60 | * | |
61 | * The block list of 'core' starts at the end of the 'diskboot' image | |
62 | * and works it's way backwards towards the end of the code of 'diskboot'. | |
63 | * | |
64 | * We patch up the images with the necessary values and write out the | |
65 | * result. | |
66 | */ | |
67 | ||
1cc73a62 | 68 | #define DEFAULT_BOOT_FILE "boot.img" |
69 | #define DEFAULT_CORE_FILE "core.img" | |
70 | ||
dd73313c | 71 | /* Non-printable "keys" for arguments with no short form. |
35b90906 | 72 | * See grub-core/lib/gnulib/argp.h for details. */ |
dd73313c JM |
73 | enum { |
74 | NO_RS_CODES_KEY = 0x100, | |
75 | }; | |
76 | ||
c5930ec8 YB |
77 | static struct argp_option options[] = { |
78 | {"boot-image", 'b', N_("FILE"), 0, | |
6a656b0e | 79 | N_("use FILE as the boot image [default=%s]"), 0}, |
c5930ec8 | 80 | {"core-image", 'c', N_("FILE"), 0, |
6a656b0e | 81 | N_("use FILE as the core image [default=%s]"), 0}, |
c5930ec8 | 82 | {"directory", 'd', N_("DIR"), 0, |
6a656b0e | 83 | N_("use GRUB files in the directory DIR [default=%s]"), 0}, |
c5930ec8 | 84 | {"device-map", 'm', N_("FILE"), 0, |
9c4b5c13 | 85 | N_("use FILE as the device map [default=%s]"), 0}, |
c5930ec8 | 86 | {"force", 'f', 0, 0, |
9c4b5c13 | 87 | N_("install even if problems are detected"), 0}, |
c5930ec8 | 88 | {"skip-fs-probe",'s',0, 0, |
6a656b0e | 89 | N_("do not probe for filesystems in DEVICE"), 0}, |
b525fd83 | 90 | {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, |
fdf2ec9c | 91 | {"allow-floppy", 'a', 0, 0, |
ef292a87 VS |
92 | /* TRANSLATORS: The potential breakage isn't limited to floppies but it's |
93 | likely to make the install unbootable from HDD. */ | |
6a656b0e | 94 | N_("make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0}, |
dd73313c JM |
95 | {"no-rs-codes", NO_RS_CODES_KEY, 0, 0, |
96 | N_("Do not apply any reed-solomon codes when embedding core.img. " | |
97 | "This option is only available on x86 BIOS targets."), 0}, | |
c5930ec8 YB |
98 | { 0, 0, 0, 0, 0, 0 } |
99 | }; | |
100 | ||
ae558c2c VS |
101 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" |
102 | ||
c5930ec8 YB |
103 | static char * |
104 | help_filter (int key, const char *text, void *input __attribute__ ((unused))) | |
105 | { | |
106 | switch (key) | |
107 | { | |
108 | case 'b': | |
109 | return xasprintf (text, DEFAULT_BOOT_FILE); | |
110 | ||
111 | case 'c': | |
112 | return xasprintf (text, DEFAULT_CORE_FILE); | |
113 | ||
114 | case 'd': | |
115 | return xasprintf (text, DEFAULT_DIRECTORY); | |
116 | ||
117 | case 'm': | |
118 | return xasprintf (text, DEFAULT_DEVICE_MAP); | |
1cc73a62 | 119 | |
c5930ec8 YB |
120 | default: |
121 | return (char *) text; | |
122 | } | |
123 | } | |
124 | ||
ae558c2c VS |
125 | #pragma GCC diagnostic error "-Wformat-nonliteral" |
126 | ||
c5930ec8 YB |
127 | struct arguments |
128 | { | |
129 | char *boot_file; | |
130 | char *core_file; | |
131 | char *dir; | |
132 | char *dev_map; | |
c5930ec8 YB |
133 | int force; |
134 | int fs_probe; | |
fdf2ec9c | 135 | int allow_floppy; |
c5930ec8 | 136 | char *device; |
dd73313c | 137 | int add_rs_codes; |
c5930ec8 YB |
138 | }; |
139 | ||
c5930ec8 YB |
140 | static error_t |
141 | argp_parser (int key, char *arg, struct argp_state *state) | |
142 | { | |
143 | /* Get the input argument from argp_parse, which we | |
144 | know is a pointer to our arguments structure. */ | |
145 | struct arguments *arguments = state->input; | |
146 | ||
c5930ec8 YB |
147 | switch (key) |
148 | { | |
fdf2ec9c VS |
149 | case 'a': |
150 | arguments->allow_floppy = 1; | |
151 | break; | |
152 | ||
c5930ec8 YB |
153 | case 'b': |
154 | if (arguments->boot_file) | |
155 | free (arguments->boot_file); | |
156 | ||
157 | arguments->boot_file = xstrdup (arg); | |
158 | break; | |
159 | ||
160 | case 'c': | |
161 | if (arguments->core_file) | |
162 | free (arguments->core_file); | |
163 | ||
164 | arguments->core_file = xstrdup (arg); | |
165 | break; | |
166 | ||
167 | case 'd': | |
168 | if (arguments->dir) | |
169 | free (arguments->dir); | |
170 | ||
171 | arguments->dir = xstrdup (arg); | |
172 | break; | |
173 | ||
174 | case 'm': | |
175 | if (arguments->dev_map) | |
176 | free (arguments->dev_map); | |
177 | ||
178 | arguments->dev_map = xstrdup (arg); | |
179 | break; | |
180 | ||
c5930ec8 YB |
181 | case 'f': |
182 | arguments->force = 1; | |
183 | break; | |
184 | ||
185 | case 's': | |
186 | arguments->fs_probe = 0; | |
187 | break; | |
188 | ||
189 | case 'v': | |
190 | verbosity++; | |
191 | break; | |
192 | ||
dd73313c JM |
193 | case NO_RS_CODES_KEY: |
194 | arguments->add_rs_codes = 0; | |
195 | break; | |
196 | ||
c5930ec8 YB |
197 | case ARGP_KEY_ARG: |
198 | if (state->arg_num == 0) | |
199 | arguments->device = xstrdup(arg); | |
200 | else | |
201 | { | |
202 | /* Too many arguments. */ | |
67093bc0 VS |
203 | fprintf (stderr, _("Unknown extra argument `%s'."), arg); |
204 | fprintf (stderr, "\n"); | |
c5930ec8 YB |
205 | argp_usage (state); |
206 | } | |
207 | break; | |
208 | ||
209 | case ARGP_KEY_NO_ARGS: | |
dfe3b247 | 210 | fprintf (stderr, "%s", _("No device is specified.\n")); |
c5930ec8 | 211 | argp_usage (state); |
c76899a0 | 212 | exit (1); |
c5930ec8 YB |
213 | break; |
214 | ||
215 | default: | |
216 | return ARGP_ERR_UNKNOWN; | |
217 | } | |
218 | ||
219 | return 0; | |
1cc73a62 | 220 | } |
221 | ||
c5930ec8 YB |
222 | static struct argp argp = { |
223 | options, argp_parser, N_("DEVICE"), | |
934d7e44 | 224 | "\n"N_("\ |
c5930ec8 YB |
225 | Set up images to boot from DEVICE.\n\ |
226 | \n\ | |
934d7e44 YB |
227 | You should not normally run this program directly. Use grub-install instead.") |
228 | "\v"N_("\ | |
26c53dc6 | 229 | DEVICE must be an OS device (e.g. /dev/sda)."), |
c5930ec8 YB |
230 | NULL, help_filter, NULL |
231 | }; | |
232 | ||
f585c905 AB |
233 | static char * |
234 | get_device_name (char *dev) | |
235 | { | |
236 | size_t len = strlen (dev); | |
237 | ||
238 | if (dev[0] != '(' || dev[len - 1] != ')') | |
239 | return 0; | |
240 | ||
241 | dev[len - 1] = '\0'; | |
242 | return dev + 1; | |
243 | } | |
244 | ||
1cc73a62 | 245 | int |
246 | main (int argc, char *argv[]) | |
247 | { | |
f585c905 AB |
248 | char *root_dev = NULL; |
249 | char *dest_dev = NULL; | |
c5930ec8 | 250 | struct arguments arguments; |
b39f9d20 | 251 | |
ae5540d3 | 252 | grub_util_host_init (&argc, &argv); |
1cc73a62 | 253 | |
c5930ec8 YB |
254 | /* Default option values. */ |
255 | memset (&arguments, 0, sizeof (struct arguments)); | |
256 | arguments.fs_probe = 1; | |
dd73313c | 257 | arguments.add_rs_codes = 1; |
1cc73a62 | 258 | |
c5930ec8 YB |
259 | /* Parse our arguments */ |
260 | if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) | |
261 | { | |
dfe3b247 | 262 | fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); |
c5930ec8 | 263 | exit(1); |
1cc73a62 | 264 | } |
265 | ||
c36e5cd1 | 266 | #ifdef GRUB_SETUP_SPARC64 |
17821956 VS |
267 | arguments.force = 1; |
268 | #endif | |
269 | ||
91a4bf68 | 270 | if (verbosity > 1) |
271 | grub_env_set ("debug", "all"); | |
272 | ||
075a1650 | 273 | /* Initialize the emulated biosdisk driver. */ |
c5930ec8 | 274 | grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP); |
1cc73a62 | 275 | |
daf0f0ba | 276 | /* Initialize all modules. */ |
277 | grub_init_all (); | |
5c144cc8 | 278 | grub_gcry_init_all (); |
b39f9d20 | 279 | |
88b87c93 | 280 | grub_lvm_fini (); |
1e8d555b VS |
281 | grub_mdraid09_fini (); |
282 | grub_mdraid1x_fini (); | |
076e7c0f VS |
283 | grub_diskfilter_fini (); |
284 | grub_diskfilter_init (); | |
1e8d555b VS |
285 | grub_mdraid09_init (); |
286 | grub_mdraid1x_init (); | |
88b87c93 VS |
287 | grub_lvm_init (); |
288 | ||
f585c905 AB |
289 | dest_dev = get_device_name (arguments.device); |
290 | if (! dest_dev) | |
291 | { | |
292 | /* Possibly, the user specified an OS device file. */ | |
293 | dest_dev = grub_util_get_grub_dev (arguments.device); | |
294 | if (! dest_dev) | |
295 | { | |
296 | char *program = xstrdup(program_name); | |
297 | fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device); | |
298 | argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); | |
299 | free(program); | |
300 | exit(1); | |
301 | } | |
302 | grub_util_info ("transformed OS device `%s' into GRUB device `%s'", | |
303 | arguments.device, dest_dev); | |
304 | } | |
305 | else | |
306 | { | |
307 | /* For simplicity. */ | |
308 | dest_dev = xstrdup (dest_dev); | |
309 | grub_util_info ("Using `%s' as GRUB device", dest_dev); | |
310 | } | |
311 | ||
076e7c0f | 312 | /* Do the real work. */ |
c06c7520 VS |
313 | GRUB_SETUP_FUNC (arguments.dir ? : DEFAULT_DIRECTORY, |
314 | arguments.boot_file ? : DEFAULT_BOOT_FILE, | |
315 | arguments.core_file ? : DEFAULT_CORE_FILE, | |
f585c905 | 316 | dest_dev, arguments.force, |
dd73313c | 317 | arguments.fs_probe, arguments.allow_floppy, |
5fd18f77 | 318 | arguments.add_rs_codes, 0); |
1cc73a62 | 319 | |
320 | /* Free resources. */ | |
daf0f0ba | 321 | grub_fini_all (); |
4b13b216 | 322 | grub_util_biosdisk_fini (); |
b39f9d20 | 323 | |
c5930ec8 YB |
324 | free (arguments.boot_file); |
325 | free (arguments.core_file); | |
326 | free (arguments.dir); | |
c5930ec8 YB |
327 | free (arguments.dev_map); |
328 | free (arguments.device); | |
f585c905 AB |
329 | free (root_dev); |
330 | free (dest_dev); | |
b39f9d20 | 331 | |
1cc73a62 | 332 | return 0; |
333 | } |