| /* grub-setup.c - make GRUB usable */ |
| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. |
| * |
| * GRUB is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * GRUB is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <config.h> |
| |
| #define _GNU_SOURCE 1 |
| |
| #include <string.h> |
| |
| #include <grub/types.h> |
| #include <grub/emu/misc.h> |
| #include <grub/util/misc.h> |
| #include <grub/device.h> |
| #include <grub/disk.h> |
| #include <grub/file.h> |
| #include <grub/fs.h> |
| #include <grub/partition.h> |
| #include <grub/env.h> |
| #include <grub/emu/hostdisk.h> |
| #include <grub/term.h> |
| #include <grub/i18n.h> |
| #include <grub/crypto.h> |
| #include <grub/emu/getroot.h> |
| #include <grub/util/install.h> |
| |
| #pragma GCC diagnostic ignored "-Wmissing-prototypes" |
| #pragma GCC diagnostic ignored "-Wmissing-declarations" |
| #include <argp.h> |
| #pragma GCC diagnostic error "-Wmissing-prototypes" |
| #pragma GCC diagnostic error "-Wmissing-declarations" |
| |
| /* On SPARC this program fills in various fields inside of the 'boot' and 'core' |
| * image files. |
| * |
| * The 'boot' image needs to know the OBP path name of the root |
| * device. It also needs to know the initial block number of |
| * 'core' (which is 'diskboot' concatenated with 'kernel' and |
| * all the modules, this is created by grub-mkimage). This resulting |
| * 'boot' image is 512 bytes in size and is placed in the second block |
| * of a partition. |
| * |
| * The initial 'diskboot' block acts as a loader for the actual GRUB |
| * kernel. It contains the loading code and then a block list. |
| * |
| * The block list of 'core' starts at the end of the 'diskboot' image |
| * and works it's way backwards towards the end of the code of 'diskboot'. |
| * |
| * We patch up the images with the necessary values and write out the |
| * result. |
| */ |
| |
| #define DEFAULT_BOOT_FILE "boot.img" |
| #define DEFAULT_CORE_FILE "core.img" |
| |
| /* Non-printable "keys" for arguments with no short form. |
| * See grub-core/gnulib/argp.h for details. */ |
| enum { |
| NO_RS_CODES_KEY = 0x100, |
| }; |
| |
| static struct argp_option options[] = { |
| {"boot-image", 'b', N_("FILE"), 0, |
| N_("use FILE as the boot image [default=%s]"), 0}, |
| {"core-image", 'c', N_("FILE"), 0, |
| N_("use FILE as the core image [default=%s]"), 0}, |
| {"directory", 'd', N_("DIR"), 0, |
| N_("use GRUB files in the directory DIR [default=%s]"), 0}, |
| {"device-map", 'm', N_("FILE"), 0, |
| N_("use FILE as the device map [default=%s]"), 0}, |
| {"force", 'f', 0, 0, |
| N_("install even if problems are detected"), 0}, |
| {"skip-fs-probe",'s',0, 0, |
| N_("do not probe for filesystems in DEVICE"), 0}, |
| {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, |
| {"allow-floppy", 'a', 0, 0, |
| /* TRANSLATORS: The potential breakage isn't limited to floppies but it's |
| likely to make the install unbootable from HDD. */ |
| N_("make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0}, |
| {"no-rs-codes", NO_RS_CODES_KEY, 0, 0, |
| N_("Do not apply any reed-solomon codes when embedding core.img. " |
| "This option is only available on x86 BIOS targets."), 0}, |
| { 0, 0, 0, 0, 0, 0 } |
| }; |
| |
| #pragma GCC diagnostic ignored "-Wformat-nonliteral" |
| |
| static char * |
| help_filter (int key, const char *text, void *input __attribute__ ((unused))) |
| { |
| switch (key) |
| { |
| case 'b': |
| return xasprintf (text, DEFAULT_BOOT_FILE); |
| |
| case 'c': |
| return xasprintf (text, DEFAULT_CORE_FILE); |
| |
| case 'd': |
| return xasprintf (text, DEFAULT_DIRECTORY); |
| |
| case 'm': |
| return xasprintf (text, DEFAULT_DEVICE_MAP); |
| |
| default: |
| return (char *) text; |
| } |
| } |
| |
| #pragma GCC diagnostic error "-Wformat-nonliteral" |
| |
| struct arguments |
| { |
| char *boot_file; |
| char *core_file; |
| char *dir; |
| char *dev_map; |
| int force; |
| int fs_probe; |
| int allow_floppy; |
| char *device; |
| int add_rs_codes; |
| }; |
| |
| static error_t |
| argp_parser (int key, char *arg, struct argp_state *state) |
| { |
| /* Get the input argument from argp_parse, which we |
| know is a pointer to our arguments structure. */ |
| struct arguments *arguments = state->input; |
| |
| switch (key) |
| { |
| case 'a': |
| arguments->allow_floppy = 1; |
| break; |
| |
| case 'b': |
| if (arguments->boot_file) |
| free (arguments->boot_file); |
| |
| arguments->boot_file = xstrdup (arg); |
| break; |
| |
| case 'c': |
| if (arguments->core_file) |
| free (arguments->core_file); |
| |
| arguments->core_file = xstrdup (arg); |
| break; |
| |
| case 'd': |
| if (arguments->dir) |
| free (arguments->dir); |
| |
| arguments->dir = xstrdup (arg); |
| break; |
| |
| case 'm': |
| if (arguments->dev_map) |
| free (arguments->dev_map); |
| |
| arguments->dev_map = xstrdup (arg); |
| break; |
| |
| case 'f': |
| arguments->force = 1; |
| break; |
| |
| case 's': |
| arguments->fs_probe = 0; |
| break; |
| |
| case 'v': |
| verbosity++; |
| break; |
| |
| case NO_RS_CODES_KEY: |
| arguments->add_rs_codes = 0; |
| break; |
| |
| case ARGP_KEY_ARG: |
| if (state->arg_num == 0) |
| arguments->device = xstrdup(arg); |
| else |
| { |
| /* Too many arguments. */ |
| fprintf (stderr, _("Unknown extra argument `%s'."), arg); |
| fprintf (stderr, "\n"); |
| argp_usage (state); |
| } |
| break; |
| |
| case ARGP_KEY_NO_ARGS: |
| fprintf (stderr, "%s", _("No device is specified.\n")); |
| argp_usage (state); |
| exit (1); |
| break; |
| |
| default: |
| return ARGP_ERR_UNKNOWN; |
| } |
| |
| return 0; |
| } |
| |
| static struct argp argp = { |
| options, argp_parser, N_("DEVICE"), |
| "\n"N_("\ |
| Set up images to boot from DEVICE.\n\ |
| \n\ |
| You should not normally run this program directly. Use grub-install instead.") |
| "\v"N_("\ |
| DEVICE must be an OS device (e.g. /dev/sda)."), |
| NULL, help_filter, NULL |
| }; |
| |
| static char * |
| get_device_name (char *dev) |
| { |
| size_t len = strlen (dev); |
| |
| if (dev[0] != '(' || dev[len - 1] != ')') |
| return 0; |
| |
| dev[len - 1] = '\0'; |
| return dev + 1; |
| } |
| |
| int |
| main (int argc, char *argv[]) |
| { |
| char *root_dev = NULL; |
| char *dest_dev = NULL; |
| struct arguments arguments; |
| |
| grub_util_host_init (&argc, &argv); |
| |
| /* Default option values. */ |
| memset (&arguments, 0, sizeof (struct arguments)); |
| arguments.fs_probe = 1; |
| arguments.add_rs_codes = 1; |
| |
| /* Parse our arguments */ |
| if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) |
| { |
| fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); |
| exit(1); |
| } |
| |
| #ifdef GRUB_SETUP_SPARC64 |
| arguments.force = 1; |
| #endif |
| |
| if (verbosity > 1) |
| grub_env_set ("debug", "all"); |
| |
| /* Initialize the emulated biosdisk driver. */ |
| grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP); |
| |
| /* Initialize all modules. */ |
| grub_init_all (); |
| grub_gcry_init_all (); |
| |
| grub_lvm_fini (); |
| grub_mdraid09_fini (); |
| grub_mdraid1x_fini (); |
| grub_diskfilter_fini (); |
| grub_diskfilter_init (); |
| grub_mdraid09_init (); |
| grub_mdraid1x_init (); |
| grub_lvm_init (); |
| |
| dest_dev = get_device_name (arguments.device); |
| if (! dest_dev) |
| { |
| /* Possibly, the user specified an OS device file. */ |
| dest_dev = grub_util_get_grub_dev (arguments.device); |
| if (! dest_dev) |
| { |
| char *program = xstrdup(program_name); |
| fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device); |
| argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); |
| free(program); |
| exit(1); |
| } |
| grub_util_info ("transformed OS device `%s' into GRUB device `%s'", |
| arguments.device, dest_dev); |
| } |
| else |
| { |
| /* For simplicity. */ |
| dest_dev = xstrdup (dest_dev); |
| grub_util_info ("Using `%s' as GRUB device", dest_dev); |
| } |
| |
| /* Do the real work. */ |
| GRUB_SETUP_FUNC (arguments.dir ? : DEFAULT_DIRECTORY, |
| arguments.boot_file ? : DEFAULT_BOOT_FILE, |
| arguments.core_file ? : DEFAULT_CORE_FILE, |
| dest_dev, arguments.force, |
| arguments.fs_probe, arguments.allow_floppy, |
| arguments.add_rs_codes); |
| |
| /* Free resources. */ |
| grub_fini_all (); |
| grub_util_biosdisk_fini (); |
| |
| free (arguments.boot_file); |
| free (arguments.core_file); |
| free (arguments.dir); |
| free (arguments.dev_map); |
| free (arguments.device); |
| free (root_dev); |
| free (dest_dev); |
| |
| return 0; |
| } |