search_wrap.c 6.54 KB
Newer Older
phcoder's avatar
phcoder committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* search.c - search devices based on a file or a filesystem label */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2005,2007,2008,2009  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/>.
 */

20 21 22 23 24 25 26
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/extcmd.h>
27
#include <grub/search.h>
28
#include <grub/i18n.h>
29

30 31
GRUB_MOD_LICENSE ("GPLv3+");

phcoder's avatar
phcoder committed
32 33
static const struct grub_arg_option options[] =
  {
34 35 36 37 38 39
    {"file",		'f', 0, N_("Search devices by a file."), 0, 0},
    {"label",		'l', 0, N_("Search devices by a filesystem label."),
     0, 0},
    {"fs-uuid",		'u', 0, N_("Search devices by a filesystem UUID."),
     0, 0},
    {"set",		's', GRUB_ARG_OPTION_OPTIONAL,
40 41
     N_("Set a variable to the first device found."), N_("VARNAME"),
     ARG_TYPE_STRING},
42
    {"no-floppy",	'n', 0, N_("Do not probe any floppy drive."), 0, 0},
43
    {"hint",	        'h', GRUB_ARG_OPTION_REPEATABLE,
44 45
     N_("First try the device HINT. If HINT ends in comma, "
	"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
46
    {"hint-ieee1275",   0, GRUB_ARG_OPTION_REPEATABLE,
47 48 49
     N_("First try the device HINT if currently running on IEEE1275. "
	"If HINT ends in comma, also try subpartitions"),
     N_("HINT"), ARG_TYPE_STRING},
50
    {"hint-bios",   0, GRUB_ARG_OPTION_REPEATABLE,
51
     N_("First try the device HINT if currently running on BIOS. "
52 53
	"If HINT ends in comma, also try subpartitions"),
     N_("HINT"), ARG_TYPE_STRING},
54
    {"hint-baremetal",   0, GRUB_ARG_OPTION_REPEATABLE,
55
     N_("First try the device HINT if direct hardware access is supported. "
56 57
	"If HINT ends in comma, also try subpartitions"),
     N_("HINT"), ARG_TYPE_STRING},
58
    {"hint-efi",   0, GRUB_ARG_OPTION_REPEATABLE,
59
     N_("First try the device HINT if currently running on EFI. "
60 61
	"If HINT ends in comma, also try subpartitions"),
     N_("HINT"), ARG_TYPE_STRING},
62
    {"hint-arc",   0, GRUB_ARG_OPTION_REPEATABLE,
63
     N_("First try the device HINT if currently running on ARC."
64 65
	" If HINT ends in comma, also try subpartitions"),
     N_("HINT"), ARG_TYPE_STRING},
phcoder's avatar
phcoder committed
66 67 68 69 70 71 72 73 74 75
    {0, 0, 0, 0, 0, 0}
  };

enum options
  {
    SEARCH_FILE,
    SEARCH_LABEL,
    SEARCH_FS_UUID,
    SEARCH_SET,
    SEARCH_NO_FLOPPY,
76 77 78 79 80 81
    SEARCH_HINT,
    SEARCH_HINT_IEEE1275,
    SEARCH_HINT_BIOS,
    SEARCH_HINT_BAREMETAL,
    SEARCH_HINT_EFI,
    SEARCH_HINT_ARC,
phcoder's avatar
phcoder committed
82 83 84
 };

static grub_err_t
85
grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
phcoder's avatar
phcoder committed
86
{
87
  struct grub_arg_list *state = ctxt->state;
phcoder's avatar
phcoder committed
88
  const char *var = 0;
89
  const char *id = 0;
90 91
  int i = 0, j = 0, nhints = 0;
  char **hints = NULL;
92 93

  if (state[SEARCH_HINT].set)
94
    for (i = 0; state[SEARCH_HINT].args[i]; i++)
95
      nhints++;
phcoder's avatar
phcoder committed
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
#ifdef GRUB_MACHINE_IEEE1275
  if (state[SEARCH_HINT_IEEE1275].set)
    for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
      nhints++;
#endif

#ifdef GRUB_MACHINE_EFI
  if (state[SEARCH_HINT_EFI].set)
    for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
      nhints++;
#endif

#ifdef GRUB_MACHINE_PCBIOS
  if (state[SEARCH_HINT_BIOS].set)
    for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
      nhints++;
#endif

#ifdef GRUB_MACHINE_ARC
  if (state[SEARCH_HINT_ARC].set)
    for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
      nhints++;
#endif

  if (state[SEARCH_HINT_BAREMETAL].set)
    for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
      nhints++;

  hints = grub_malloc (sizeof (hints[0]) * nhints);
  if (!hints)
    return grub_errno;
  j = 0;

  if (state[SEARCH_HINT].set)
    for (i = 0; state[SEARCH_HINT].args[i]; i++)
      hints[j++] = state[SEARCH_HINT].args[i];

#ifdef GRUB_MACHINE_IEEE1275
  if (state[SEARCH_HINT_IEEE1275].set)
    for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
      hints[j++] = state[SEARCH_HINT_IEEE1275].args[i];
#endif

#ifdef GRUB_MACHINE_EFI
  if (state[SEARCH_HINT_EFI].set)
    for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
      hints[j++] = state[SEARCH_HINT_EFI].args[i];
#endif

#ifdef GRUB_MACHINE_ARC
  if (state[SEARCH_HINT_ARC].set)
    for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
      hints[j++] = state[SEARCH_HINT_ARC].args[i];
#endif

#ifdef GRUB_MACHINE_PCBIOS
  if (state[SEARCH_HINT_BIOS].set)
    for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
      hints[j++] = state[SEARCH_HINT_BIOS].args[i];
#endif

  if (state[SEARCH_HINT_BAREMETAL].set)
    for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
      hints[j++] = state[SEARCH_HINT_BAREMETAL].args[i];

  /* Skip hints for future platforms.  */
  for (j = 0; j < argc; j++)
    if (grub_memcmp (args[j], "--hint-", sizeof ("--hint-") - 1) != 0)
      break;

phcoder's avatar
phcoder committed
167 168 169
  if (state[SEARCH_SET].set)
    var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";

170 171 172 173 174 175 176 177
  if (argc != j)
    id = args[j];
  else if (state[SEARCH_SET].set && state[SEARCH_SET].arg)
    {
      id = state[SEARCH_SET].arg;
      var = "root";
    }
  else
178 179 180 181
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
      goto out;
    }
182

phcoder's avatar
phcoder committed
183
  if (state[SEARCH_LABEL].set)
184
    grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, 
185
		       hints, nhints);
phcoder's avatar
phcoder committed
186
  else if (state[SEARCH_FS_UUID].set)
187
    grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set,
188
			 hints, nhints);
phcoder's avatar
phcoder committed
189
  else if (state[SEARCH_FILE].set)
190
    grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, 
191
			 hints, nhints);
phcoder's avatar
phcoder committed
192
  else
193
    grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
phcoder's avatar
phcoder committed
194

195 196
out:
  grub_free (hints);
phcoder's avatar
phcoder committed
197 198 199 200 201 202 203 204
  return grub_errno;
}

static grub_extcmd_t cmd;

GRUB_MOD_INIT(search)
{
  cmd =
205 206
    grub_register_extcmd ("search", grub_cmd_search,
			  GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
207 208
			  N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
			     " NAME"),
209 210 211 212
			  N_("Search devices by file, filesystem label"
			     " or filesystem UUID."
			     " If --set is specified, the first device found is"
			     " set to a variable. If no variable name is"
213
			     " specified, `root' is used."),
phcoder's avatar
phcoder committed
214 215 216 217 218 219 220
			  options);
}

GRUB_MOD_FINI(search)
{
  grub_unregister_extcmd (cmd);
}