]> git.proxmox.com Git - grub2.git/blob - util/grub-setup.c
90b9de0136e510210461c62f70791070be87ea8d
[grub2.git] / util / grub-setup.c
1 /* grub-setup.c - make GRUB usable */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
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
20 #include <config.h>
21
22 #define _GNU_SOURCE 1
23
24 #include <string.h>
25
26 #include <grub/types.h>
27 #include <grub/emu/misc.h>
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>
33 #include <grub/partition.h>
34 #include <grub/env.h>
35 #include <grub/emu/hostdisk.h>
36 #include <grub/term.h>
37 #include <grub/i18n.h>
38 #include <grub/crypto.h>
39 #include <grub/emu/getroot.h>
40 #include <grub/util/install.h>
41
42 #include <argp.h>
43
44 /* On SPARC this program fills in various fields inside of the 'boot' and 'core'
45 * image files.
46 *
47 * The 'boot' image needs to know the OBP path name of the root
48 * device. It also needs to know the initial block number of
49 * 'core' (which is 'diskboot' concatenated with 'kernel' and
50 * all the modules, this is created by grub-mkimage). This resulting
51 * 'boot' image is 512 bytes in size and is placed in the second block
52 * of a partition.
53 *
54 * The initial 'diskboot' block acts as a loader for the actual GRUB
55 * kernel. It contains the loading code and then a block list.
56 *
57 * The block list of 'core' starts at the end of the 'diskboot' image
58 * and works it's way backwards towards the end of the code of 'diskboot'.
59 *
60 * We patch up the images with the necessary values and write out the
61 * result.
62 */
63
64 #define DEFAULT_BOOT_FILE "boot.img"
65 #define DEFAULT_CORE_FILE "core.img"
66
67 static struct argp_option options[] = {
68 {"boot-image", 'b', N_("FILE"), 0,
69 N_("use FILE as the boot image [default=%s]"), 0},
70 {"core-image", 'c', N_("FILE"), 0,
71 N_("use FILE as the core image [default=%s]"), 0},
72 {"directory", 'd', N_("DIR"), 0,
73 N_("use GRUB files in the directory DIR [default=%s]"), 0},
74 {"device-map", 'm', N_("FILE"), 0,
75 N_("use FILE as the device map [default=%s]"), 0},
76 {"force", 'f', 0, 0,
77 N_("install even if problems are detected"), 0},
78 {"skip-fs-probe",'s',0, 0,
79 N_("do not probe for filesystems in DEVICE"), 0},
80 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
81 {"allow-floppy", 'a', 0, 0,
82 /* TRANSLATORS: The potential breakage isn't limited to floppies but it's
83 likely to make the install unbootable from HDD. */
84 N_("make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0},
85
86 { 0, 0, 0, 0, 0, 0 }
87 };
88
89 static char *
90 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
91 {
92 switch (key)
93 {
94 case 'b':
95 return xasprintf (text, DEFAULT_BOOT_FILE);
96
97 case 'c':
98 return xasprintf (text, DEFAULT_CORE_FILE);
99
100 case 'd':
101 return xasprintf (text, DEFAULT_DIRECTORY);
102
103 case 'm':
104 return xasprintf (text, DEFAULT_DEVICE_MAP);
105
106 default:
107 return (char *) text;
108 }
109 }
110
111 struct arguments
112 {
113 char *boot_file;
114 char *core_file;
115 char *dir;
116 char *dev_map;
117 int force;
118 int fs_probe;
119 int allow_floppy;
120 char *device;
121 };
122
123 static error_t
124 argp_parser (int key, char *arg, struct argp_state *state)
125 {
126 /* Get the input argument from argp_parse, which we
127 know is a pointer to our arguments structure. */
128 struct arguments *arguments = state->input;
129
130 switch (key)
131 {
132 case 'a':
133 arguments->allow_floppy = 1;
134 break;
135
136 case 'b':
137 if (arguments->boot_file)
138 free (arguments->boot_file);
139
140 arguments->boot_file = xstrdup (arg);
141 break;
142
143 case 'c':
144 if (arguments->core_file)
145 free (arguments->core_file);
146
147 arguments->core_file = xstrdup (arg);
148 break;
149
150 case 'd':
151 if (arguments->dir)
152 free (arguments->dir);
153
154 arguments->dir = xstrdup (arg);
155 break;
156
157 case 'm':
158 if (arguments->dev_map)
159 free (arguments->dev_map);
160
161 arguments->dev_map = xstrdup (arg);
162 break;
163
164 case 'f':
165 arguments->force = 1;
166 break;
167
168 case 's':
169 arguments->fs_probe = 0;
170 break;
171
172 case 'v':
173 verbosity++;
174 break;
175
176 case ARGP_KEY_ARG:
177 if (state->arg_num == 0)
178 arguments->device = xstrdup(arg);
179 else
180 {
181 /* Too many arguments. */
182 fprintf (stderr, _("Unknown extra argument `%s'."), arg);
183 fprintf (stderr, "\n");
184 argp_usage (state);
185 }
186 break;
187
188 case ARGP_KEY_NO_ARGS:
189 fprintf (stderr, "%s", _("No device is specified.\n"));
190 argp_usage (state);
191 exit (1);
192 break;
193
194 default:
195 return ARGP_ERR_UNKNOWN;
196 }
197
198 return 0;
199 }
200
201 static struct argp argp = {
202 options, argp_parser, N_("DEVICE"),
203 "\n"N_("\
204 Set up images to boot from DEVICE.\n\
205 \n\
206 You should not normally run this program directly. Use grub-install instead.")
207 "\v"N_("\
208 DEVICE must be an OS device (e.g. /dev/sda)."),
209 NULL, help_filter, NULL
210 };
211
212 static char *
213 get_device_name (char *dev)
214 {
215 size_t len = strlen (dev);
216
217 if (dev[0] != '(' || dev[len - 1] != ')')
218 return 0;
219
220 dev[len - 1] = '\0';
221 return dev + 1;
222 }
223
224 int
225 main (int argc, char *argv[])
226 {
227 char *root_dev = NULL;
228 char *dest_dev = NULL;
229 struct arguments arguments;
230
231 grub_util_host_init (&argc, &argv);
232
233 /* Default option values. */
234 memset (&arguments, 0, sizeof (struct arguments));
235 arguments.fs_probe = 1;
236
237 /* Parse our arguments */
238 if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
239 {
240 fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
241 exit(1);
242 }
243
244 #ifdef GRUB_SETUP_SPARC64
245 arguments.force = 1;
246 #endif
247
248 if (verbosity > 1)
249 grub_env_set ("debug", "all");
250
251 /* Initialize the emulated biosdisk driver. */
252 grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP);
253
254 /* Initialize all modules. */
255 grub_init_all ();
256 grub_gcry_init_all ();
257
258 grub_lvm_fini ();
259 grub_mdraid09_fini ();
260 grub_mdraid1x_fini ();
261 grub_diskfilter_fini ();
262 grub_diskfilter_init ();
263 grub_mdraid09_init ();
264 grub_mdraid1x_init ();
265 grub_lvm_init ();
266
267 dest_dev = get_device_name (arguments.device);
268 if (! dest_dev)
269 {
270 /* Possibly, the user specified an OS device file. */
271 dest_dev = grub_util_get_grub_dev (arguments.device);
272 if (! dest_dev)
273 {
274 char *program = xstrdup(program_name);
275 fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device);
276 argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
277 free(program);
278 exit(1);
279 }
280 grub_util_info ("transformed OS device `%s' into GRUB device `%s'",
281 arguments.device, dest_dev);
282 }
283 else
284 {
285 /* For simplicity. */
286 dest_dev = xstrdup (dest_dev);
287 grub_util_info ("Using `%s' as GRUB device", dest_dev);
288 }
289
290 /* Do the real work. */
291 GRUB_SETUP_FUNC (arguments.dir ? : DEFAULT_DIRECTORY,
292 arguments.boot_file ? : DEFAULT_BOOT_FILE,
293 arguments.core_file ? : DEFAULT_CORE_FILE,
294 dest_dev, arguments.force,
295 arguments.fs_probe, arguments.allow_floppy);
296
297 /* Free resources. */
298 grub_fini_all ();
299 grub_util_biosdisk_fini ();
300
301 free (arguments.boot_file);
302 free (arguments.core_file);
303 free (arguments.dir);
304 free (arguments.dev_map);
305 free (arguments.device);
306 free (root_dev);
307 free (dest_dev);
308
309 return 0;
310 }