~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to util/sparc64/ieee1275/grub-setup.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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  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
 
#include <grub/types.h>
22
 
#include <grub/util/misc.h>
23
 
#include <grub/device.h>
24
 
#include <grub/i18n.h>
25
 
#include <grub/disk.h>
26
 
#include <grub/file.h>
27
 
#include <grub/fs.h>
28
 
#include <grub/partition.h>
29
 
#include <grub/msdos_partition.h>
30
 
#include <grub/gpt_partition.h>
31
 
#include <grub/env.h>
32
 
#include <grub/emu/hostdisk.h>
33
 
#include <grub/machine/boot.h>
34
 
#include <grub/machine/kernel.h>
35
 
#include <grub/term.h>
36
 
#include <grub/util/raid.h>
37
 
#include <grub/util/lvm.h>
38
 
#include <grub/util/ofpath.h>
39
 
 
40
 
#include <grub_setup_init.h>
41
 
 
42
 
#include <stdio.h>
43
 
#include <unistd.h>
44
 
#include <string.h>
45
 
#include <stdlib.h>
46
 
#include <sys/types.h>
47
 
#include <sys/stat.h>
48
 
#include <dirent.h>
49
 
#include <grub/emu/getroot.h>
50
 
 
51
 
#define _GNU_SOURCE     1
52
 
#include <getopt.h>
53
 
 
54
 
#include "progname.h"
55
 
 
56
 
/* This program fills in various fields inside of the 'boot' and 'core'
57
 
 * image files.
58
 
 *
59
 
 * The 'boot' image needs to know the OBP path name of the root
60
 
 * device.  It also needs to know the initial block number of
61
 
 * 'core' (which is 'diskboot' concatenated with 'kernel' and
62
 
 * all the modules, this is created by grub-mkimage).  This resulting
63
 
 * 'boot' image is 512 bytes in size and is placed in the second block
64
 
 * of a partition.
65
 
 *
66
 
 * The initial 'diskboot' block acts as a loader for the actual GRUB
67
 
 * kernel.  It contains the loading code and then a block list.
68
 
 *
69
 
 * The block list of 'core' starts at the end of the 'diskboot' image
70
 
 * and works it's way backwards towards the end of the code of 'diskboot'.
71
 
 *
72
 
 * We patch up the images with the necessary values and write out the
73
 
 * result.
74
 
 */
75
 
 
76
 
#define DEFAULT_BOOT_FILE       "boot.img"
77
 
#define DEFAULT_CORE_FILE       "core.img"
78
 
 
79
 
#define grub_target_to_host16(x)        grub_be_to_cpu16(x)
80
 
#define grub_target_to_host32(x)        grub_be_to_cpu32(x)
81
 
#define grub_target_to_host64(x)        grub_be_to_cpu64(x)
82
 
#define grub_host_to_target16(x)        grub_cpu_to_be16(x)
83
 
#define grub_host_to_target32(x)        grub_cpu_to_be32(x)
84
 
#define grub_host_to_target64(x)        grub_cpu_to_be64(x)
85
 
 
86
 
/* This is the blocklist used in the diskboot image.  */
87
 
struct boot_blocklist
88
 
{
89
 
  grub_uint64_t start;
90
 
  grub_uint32_t len;
91
 
} __attribute__ ((packed));
92
 
 
93
 
void 
94
 
grub_xputs_real (const char *str)
95
 
{
96
 
  fputs (str, stdout);
97
 
}
98
 
 
99
 
void (*grub_xputs) (const char *str) = grub_xputs_real;
100
 
 
101
 
int
102
 
grub_getkey (void)
103
 
{
104
 
  return -1;
105
 
}
106
 
 
107
 
void
108
 
grub_refresh (void)
109
 
{
110
 
  fflush (stdout);
111
 
}
112
 
 
113
 
static void
114
 
setup (const char *prefix, const char *dir,
115
 
       const char *boot_file, const char *core_file,
116
 
       const char *root, const char *dest)
117
 
{
118
 
  char *boot_path, *core_path;
119
 
  char *boot_img, *core_img;
120
 
  size_t boot_size, core_size;
121
 
  grub_uint16_t core_sectors;
122
 
  grub_device_t root_dev, dest_dev;
123
 
  char *boot_devpath;
124
 
  grub_disk_addr_t *kernel_byte;
125
 
  struct boot_blocklist *first_block, *block;
126
 
  char *tmp_img;
127
 
  int i;
128
 
  grub_disk_addr_t first_sector;
129
 
  grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
130
 
  grub_file_t file;
131
 
  FILE *fp;
132
 
  struct { grub_uint64_t start; grub_uint64_t end; } embed_region;
133
 
  embed_region.start = embed_region.end = ~0UL;
134
 
 
135
 
  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
136
 
                                                unsigned int offset,
137
 
                                                unsigned int length);
138
 
  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
139
 
                                              unsigned int offset,
140
 
                                              unsigned int length);
141
 
 
142
 
  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
143
 
                                           unsigned int offset,
144
 
                                           unsigned int length)
145
 
    {
146
 
      grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length);
147
 
 
148
 
      if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
149
 
        grub_util_error ("the first sector of the core file "
150
 
                         "is not sector-aligned");
151
 
 
152
 
      first_sector = sector;
153
 
    }
154
 
 
155
 
  void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
156
 
                                         unsigned int offset,
157
 
                                         unsigned int length)
158
 
    {
159
 
      struct boot_blocklist *prev = block + 1;
160
 
 
161
 
      grub_util_info ("saving <%llu,%u,%u>", sector, offset, length);
162
 
 
163
 
      if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
164
 
        grub_util_error ("non-sector-aligned data is found in the core file");
165
 
 
166
 
      if (block != first_block
167
 
          && (grub_be_to_cpu64 (prev->start)
168
 
              + grub_be_to_cpu16 (prev->len)) == sector)
169
 
        prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1);
170
 
      else
171
 
        {
172
 
          block->start = grub_cpu_to_be64 (sector);
173
 
          block->len = grub_cpu_to_be16 (1);
174
 
 
175
 
          block--;
176
 
          if (block->len)
177
 
            grub_util_error ("the sectors of the core file are too fragmented");
178
 
        }
179
 
 
180
 
      last_length = length;
181
 
    }
182
 
 
183
 
  /* Read the boot image by the OS service.  */
184
 
  boot_path = grub_util_get_path (dir, boot_file);
185
 
  boot_size = grub_util_get_image_size (boot_path);
186
 
  if (boot_size != GRUB_DISK_SECTOR_SIZE)
187
 
    grub_util_error ("the size of `%s' is not %d",
188
 
                     boot_path, GRUB_DISK_SECTOR_SIZE);
189
 
  boot_img = grub_util_read_image (boot_path);
190
 
  free (boot_path);
191
 
 
192
 
  /* Set the addresses of variables in the boot image.  */
193
 
  boot_devpath = (char *) (boot_img
194
 
                           + GRUB_BOOT_AOUT_HEADER_SIZE
195
 
                           + GRUB_BOOT_MACHINE_BOOT_DEVPATH);
196
 
  kernel_byte = (grub_disk_addr_t *) (boot_img
197
 
                                      + GRUB_BOOT_AOUT_HEADER_SIZE
198
 
                                      + GRUB_BOOT_MACHINE_KERNEL_BYTE);
199
 
 
200
 
  core_path = grub_util_get_path (dir, core_file);
201
 
  core_size = grub_util_get_image_size (core_path);
202
 
  core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
203
 
                  >> GRUB_DISK_SECTOR_BITS);
204
 
  if (core_size < GRUB_DISK_SECTOR_SIZE)
205
 
    grub_util_error ("the size of `%s' is too small", core_path);
206
 
 
207
 
  core_img = grub_util_read_image (core_path);
208
 
  free (core_path);
209
 
 
210
 
  /* Have FIRST_BLOCK to point to the first blocklist.  */
211
 
  first_block = (struct boot_blocklist *) (core_img
212
 
                                           + GRUB_DISK_SECTOR_SIZE
213
 
                                           - sizeof (*block));
214
 
 
215
 
  grub_util_info ("root is `%s', dest is `%s'", root, dest);
216
 
 
217
 
  /* Open the root device and the destination device.  */
218
 
  grub_util_info ("Opening root");
219
 
  root_dev = grub_device_open (root);
220
 
  if (! root_dev)
221
 
    grub_util_error ("%s", grub_errmsg);
222
 
 
223
 
  grub_util_info ("Opening dest");
224
 
  dest_dev = grub_device_open (dest);
225
 
  if (! dest_dev)
226
 
    grub_util_error ("%s", grub_errmsg);
227
 
 
228
 
  grub_util_info ("setting the root device to `%s'", root);
229
 
  if (grub_env_set ("root", root) != GRUB_ERR_NONE)
230
 
    grub_util_error ("%s", grub_errmsg);
231
 
 
232
 
  /* The core image must be put on a filesystem unfortunately.  */
233
 
  grub_util_info ("will leave the core image on the filesystem");
234
 
 
235
 
  /* Make sure that GRUB reads the identical image as the OS.  */
236
 
  tmp_img = xmalloc (core_size);
237
 
  core_path = grub_util_get_path (prefix, core_file);
238
 
 
239
 
  /* It is a Good Thing to sync two times.  */
240
 
  sync ();
241
 
  sync ();
242
 
 
243
 
#define MAX_TRIES       5
244
 
 
245
 
  for (i = 0; i < MAX_TRIES; i++)
246
 
    {
247
 
      grub_util_info ("attempting to read the core image `%s' from GRUB%s",
248
 
                      core_path, (i == 0) ? "" : " again");
249
 
 
250
 
      grub_disk_cache_invalidate_all ();
251
 
 
252
 
      file = grub_file_open (core_path);
253
 
      if (file)
254
 
        {
255
 
          if (grub_file_size (file) != core_size)
256
 
            grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
257
 
                            (int) grub_file_size (file), (int) core_size);
258
 
          else if (grub_file_read (file, tmp_img, core_size)
259
 
                   != (grub_ssize_t) core_size)
260
 
            grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
261
 
                            (int) core_size);
262
 
          else if (memcmp (core_img, tmp_img, core_size) != 0)
263
 
            {
264
 
#if 0
265
 
              FILE *dump;
266
 
              FILE *dump2;
267
 
 
268
 
              dump = fopen ("dump.img", "wb");
269
 
              if (dump)
270
 
                {
271
 
                  fwrite (tmp_img, 1, core_size, dump);
272
 
                  fclose (dump);
273
 
                }
274
 
 
275
 
              dump2 = fopen ("dump2.img", "wb");
276
 
              if (dump2)
277
 
                {
278
 
                  fwrite (core_img, 1, core_size, dump2);
279
 
                  fclose (dump2);
280
 
                }
281
 
 
282
 
#endif
283
 
              grub_util_info ("succeeded in opening the core image but the data is different");
284
 
            }
285
 
          else
286
 
            {
287
 
              grub_file_close (file);
288
 
              break;
289
 
            }
290
 
 
291
 
          grub_file_close (file);
292
 
        }
293
 
      else
294
 
        grub_util_info ("couldn't open the core image");
295
 
 
296
 
      if (grub_errno)
297
 
        grub_util_info ("error message = %s", grub_errmsg);
298
 
 
299
 
      grub_errno = GRUB_ERR_NONE;
300
 
      sync ();
301
 
      sleep (1);
302
 
    }
303
 
 
304
 
  if (i == MAX_TRIES)
305
 
    grub_util_error ("cannot read `%s' correctly", core_path);
306
 
 
307
 
  /* Clean out the blocklists.  */
308
 
  block = first_block;
309
 
  while (block->len)
310
 
    {
311
 
      block->start = 0;
312
 
      block->len = 0;
313
 
 
314
 
      block--;
315
 
 
316
 
      if ((char *) block <= core_img)
317
 
        grub_util_error ("no terminator in the core image");
318
 
    }
319
 
 
320
 
  /* Now read the core image to determine where the sectors are.  */
321
 
  file = grub_file_open (core_path);
322
 
  if (! file)
323
 
    grub_util_error ("%s", grub_errmsg);
324
 
 
325
 
  file->read_hook = save_first_sector;
326
 
  if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
327
 
      != GRUB_DISK_SECTOR_SIZE)
328
 
    grub_util_error ("failed to read the first sector of the core image");
329
 
 
330
 
  block = first_block;
331
 
  file->read_hook = save_blocklists;
332
 
  if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
333
 
      != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
334
 
    grub_util_error ("failed to read the rest sectors of the core image");
335
 
 
336
 
  if (file->device->disk->id != dest_dev->disk->id)
337
 
    {
338
 
      const char *dest_ofpath;
339
 
      dest_ofpath
340
 
        = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk));
341
 
      grub_util_info ("dest_ofpath is `%s'", dest_ofpath);
342
 
      strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
343
 
               - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1);
344
 
      boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
345
 
                   - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0;
346
 
    }
347
 
  else
348
 
    {
349
 
      grub_util_info ("non cross-disk install");
350
 
      memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
351
 
              - GRUB_BOOT_MACHINE_BOOT_DEVPATH);
352
 
    }
353
 
 
354
 
  grub_file_close (file);
355
 
 
356
 
  free (core_path);
357
 
  free (tmp_img);
358
 
 
359
 
  *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS);
360
 
 
361
 
  grub_util_info ("boot device path %s, prefix is %s, dest is %s",
362
 
                  boot_devpath, prefix, dest);
363
 
 
364
 
  /* Write the first two sectors of the core image onto the disk.  */
365
 
  core_path = grub_util_get_path (dir, core_file);
366
 
  grub_util_info ("opening the core image `%s'", core_path);
367
 
  fp = fopen (core_path, "r+b");
368
 
  if (! fp)
369
 
    grub_util_error ("cannot open `%s'", core_path);
370
 
 
371
 
  grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp);
372
 
  fclose (fp);
373
 
  free (core_path);
374
 
 
375
 
  /* Write the boot image onto the disk.  */
376
 
  if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
377
 
    grub_util_error ("%s", grub_errmsg);
378
 
 
379
 
  /* Sync is a Good Thing.  */
380
 
  sync ();
381
 
 
382
 
  free (core_img);
383
 
  free (boot_img);
384
 
  grub_device_close (dest_dev);
385
 
  grub_device_close (root_dev);
386
 
}
387
 
 
388
 
static struct option options[] =
389
 
  {
390
 
    {"boot-image", required_argument, 0, 'b'},
391
 
    {"core-image", required_argument, 0, 'c'},
392
 
    {"directory", required_argument, 0, 'd'},
393
 
    {"device-map", required_argument, 0, 'm'},
394
 
    {"root-device", required_argument, 0, 'r'},
395
 
    {"help", no_argument, 0, 'h'},
396
 
    {"version", no_argument, 0, 'V'},
397
 
    {"verbose", no_argument, 0, 'v'},
398
 
    {0, 0, 0, 0}
399
 
  };
400
 
 
401
 
static void
402
 
usage (int status)
403
 
{
404
 
  if (status)
405
 
    fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
406
 
  else
407
 
    printf ("\
408
 
Usage: %s [OPTION]... DEVICE\n\
409
 
\n\
410
 
Set up images to boot from DEVICE.\n\
411
 
DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\
412
 
\n\
413
 
You should not normally run %s directly.  Use grub-install instead.\n\
414
 
\n\
415
 
  -b, --boot-image=FILE   use FILE as the boot image [default=%s]\n\
416
 
  -c, --core-image=FILE   use FILE as the core image [default=%s]\n\
417
 
  -d, --directory=DIR     use GRUB files in the directory DIR [default=%s]\n\
418
 
  -m, --device-map=FILE   use FILE as the device map [default=%s]\n\
419
 
  -r, --root-device=DEV   use DEV as the root device [default=guessed]\n\
420
 
  -h, --help              display this message and exit\n\
421
 
  -V, --version           print version information and exit\n\
422
 
  -v, --verbose           print verbose messages\n\
423
 
\n\
424
 
Report bugs to <%s>.\n\
425
 
", program_name, program_name,
426
 
            DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
427
 
            DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
428
 
 
429
 
  exit (status);
430
 
}
431
 
 
432
 
struct grub_setup_info
433
 
{
434
 
  char *boot_file;
435
 
  char *core_file;
436
 
  char *dir;
437
 
  char *dev_map;
438
 
  char *root_dev;
439
 
  char *prefix;
440
 
  char *dest_dev;
441
 
};
442
 
 
443
 
static void
444
 
init_info (struct grub_setup_info *gp)
445
 
{
446
 
  gp->boot_file = NULL;
447
 
  gp->core_file = NULL;
448
 
  gp->dir = NULL;
449
 
  gp->dev_map = NULL;
450
 
  gp->root_dev = NULL;
451
 
  gp->prefix = NULL;
452
 
  gp->dest_dev = NULL;
453
 
}
454
 
 
455
 
static int
456
 
parse_options (struct grub_setup_info *gp, int argc, char *argv[])
457
 
{
458
 
  while (1)
459
 
    {
460
 
      int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0);
461
 
 
462
 
      if (c == -1)
463
 
        break;
464
 
      else
465
 
        switch (c)
466
 
          {
467
 
          case 'b':
468
 
            if (gp->boot_file)
469
 
              free (gp->boot_file);
470
 
 
471
 
            gp->boot_file = xstrdup (optarg);
472
 
            break;
473
 
 
474
 
          case 'c':
475
 
            if (gp->core_file)
476
 
              free (gp->core_file);
477
 
 
478
 
            gp->core_file = xstrdup (optarg);
479
 
            break;
480
 
 
481
 
          case 'd':
482
 
            if (gp->dir)
483
 
              free (gp->dir);
484
 
 
485
 
            gp->dir = xstrdup (optarg);
486
 
            break;
487
 
 
488
 
          case 'm':
489
 
            if (gp->dev_map)
490
 
              free (gp->dev_map);
491
 
 
492
 
            gp->dev_map = xstrdup (optarg);
493
 
            break;
494
 
 
495
 
          case 'r':
496
 
            if (gp->root_dev)
497
 
              free (gp->root_dev);
498
 
 
499
 
            gp->root_dev = xstrdup (optarg);
500
 
            break;
501
 
 
502
 
          case 'h':
503
 
            usage (0);
504
 
            break;
505
 
 
506
 
          case 'V':
507
 
            printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
508
 
            return 0;
509
 
 
510
 
          case 'v':
511
 
            verbosity++;
512
 
            break;
513
 
 
514
 
          default:
515
 
            usage (1);
516
 
            break;
517
 
          }
518
 
    }
519
 
 
520
 
  if (verbosity > 1)
521
 
    grub_env_set ("debug", "all");
522
 
 
523
 
  if (optind >= argc)
524
 
    {
525
 
      fprintf (stderr, "No device is specified.\n");
526
 
      usage (1);
527
 
    }
528
 
 
529
 
  if (optind + 1 != argc)
530
 
    {
531
 
      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
532
 
      usage (1);
533
 
    }
534
 
  return 1;
535
 
}
536
 
 
537
 
static char *
538
 
get_device_name (char *dev)
539
 
{
540
 
  size_t len = strlen (dev);
541
 
 
542
 
  if (dev[0] != '(' || dev[len - 1] != ')')
543
 
    return 0;
544
 
 
545
 
  dev[len - 1] = '\0';
546
 
  return dev + 1;
547
 
}
548
 
 
549
 
static void
550
 
find_dest_dev (struct grub_setup_info *gp, char *argv[])
551
 
{
552
 
  gp->dest_dev = get_device_name (argv[optind]);
553
 
  if (! gp->dest_dev)
554
 
    {
555
 
      /* Possibly, the user specified an OS device file.  */
556
 
      gp->dest_dev = grub_util_get_grub_dev (argv[optind]);
557
 
      if (! gp->dest_dev)
558
 
        {
559
 
          fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
560
 
          usage (1);
561
 
        }
562
 
      grub_util_info ("transformed OS device `%s' into GRUB device `%s'",
563
 
                      argv[optind], gp->dest_dev);
564
 
    }
565
 
  else
566
 
    {
567
 
      /* For simplicity.  */
568
 
      gp->dest_dev = xstrdup (gp->dest_dev);
569
 
      grub_util_info ("Using `%s' as GRUB device", gp->dest_dev);
570
 
    }
571
 
}
572
 
 
573
 
static void
574
 
check_root_dev (struct grub_setup_info *gp)
575
 
{
576
 
  if (gp->root_dev)
577
 
    {
578
 
      char *tmp = get_device_name (gp->root_dev);
579
 
 
580
 
      if (! tmp)
581
 
        grub_util_error ("invalid root device `%s'", gp->root_dev);
582
 
 
583
 
      tmp = xstrdup (tmp);
584
 
      free (gp->root_dev);
585
 
      gp->root_dev = tmp;
586
 
    }
587
 
  else
588
 
    {
589
 
      char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY;
590
 
      char *root_device = grub_guess_root_device (dir);
591
 
 
592
 
      gp->root_dev = grub_util_get_grub_dev (root_device);
593
 
      if (! gp->root_dev)
594
 
        {
595
 
          grub_util_info ("guessing the root device failed, because of `%s'",
596
 
                          grub_errmsg);
597
 
          grub_util_error ("cannot guess the root device. "
598
 
                           "Specify the option `--root-device'");
599
 
        }
600
 
      grub_util_info ("guessed root device `%s' and root_dev `%s' from "
601
 
                      "dir `%s'", root_device, gp->root_dev, dir);
602
 
    }
603
 
}
604
 
 
605
 
static void
606
 
free_memory (struct grub_setup_info *gp)
607
 
{
608
 
  free (gp->boot_file);
609
 
  free (gp->core_file);
610
 
  free (gp->dir);
611
 
  free (gp->dev_map);
612
 
  free (gp->root_dev);
613
 
  free (gp->prefix);
614
 
  free (gp->dest_dev);
615
 
}
616
 
 
617
 
int
618
 
main (int argc, char *argv[])
619
 
{
620
 
  struct grub_setup_info ginfo;
621
 
 
622
 
  set_program_name (argv[0]);
623
 
 
624
 
  grub_util_init_nls ();
625
 
 
626
 
  init_info (&ginfo);
627
 
  if (!parse_options (&ginfo, argc, argv))
628
 
    return 0;
629
 
 
630
 
  /* Initialize the emulated biosdisk driver.  */
631
 
  grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP);
632
 
 
633
 
  /* Initialize all modules. */
634
 
  grub_init_all ();
635
 
 
636
 
  find_dest_dev (&ginfo, argv);
637
 
 
638
 
  ginfo.prefix = grub_make_system_path_relative_to_its_root (ginfo.dir ?
639
 
                                                             : DEFAULT_DIRECTORY);
640
 
 
641
 
  check_root_dev (&ginfo);
642
 
 
643
 
  /* Do the real work.  */
644
 
  setup (ginfo.prefix,
645
 
         ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY,
646
 
         ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE,
647
 
         ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE,
648
 
         ginfo.root_dev, ginfo.dest_dev);
649
 
 
650
 
  /* Free resources.  */
651
 
  grub_fini_all ();
652
 
 
653
 
  free_memory (&ginfo);
654
 
 
655
 
  return 0;
656
 
}