2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <config-util.h>
22 #include <grub/emu/getroot.h>
25 #ifdef HAVE_DEVICE_MAPPER
28 #include <sys/types.h>
43 #if defined(MAJOR_IN_MKDEV)
44 #include <sys/mkdev.h>
45 #elif defined(MAJOR_IN_SYSMACROS)
46 #include <sys/sysmacros.h>
49 #include <libdevmapper.h>
51 #include <grub/types.h>
52 #include <grub/util/misc.h>
55 #include <grub/misc.h>
56 #include <grub/emu/misc.h>
57 #include <grub/emu/hostdisk.h>
60 grub_util_open_dm (const char *os_dev
, struct dm_tree
**tree
,
61 struct dm_tree_node
**node
)
69 if (stat (os_dev
, &st
) < 0)
72 maj
= major (st
.st_rdev
);
73 min
= minor (st
.st_rdev
);
75 if (!dm_is_dm_major (maj
))
78 *tree
= dm_tree_create ();
81 grub_puts_ (N_("Failed to create `device-mapper' tree"));
82 grub_dprintf ("hostdisk", "dm_tree_create failed\n");
86 if (! dm_tree_add_dev (*tree
, maj
, min
))
88 grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
94 *node
= dm_tree_find_node (*tree
, maj
, min
);
97 grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
106 get_dm_uuid (const char *os_dev
)
108 struct dm_tree
*tree
;
109 struct dm_tree_node
*node
;
110 const char *node_uuid
;
113 if (!grub_util_open_dm (os_dev
, &tree
, &node
))
116 node_uuid
= dm_tree_node_get_uuid (node
);
119 grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev
);
124 ret
= grub_strdup (node_uuid
);
131 enum grub_dev_abstraction_types
132 grub_util_get_dm_abstraction (const char *os_dev
)
136 uuid
= get_dm_uuid (os_dev
);
139 return GRUB_DEV_ABSTRACTION_NONE
;
141 if (strncmp (uuid
, "LVM-", 4) == 0)
144 return GRUB_DEV_ABSTRACTION_LVM
;
146 if (strncmp (uuid
, "CRYPT-LUKS1-", 12) == 0)
149 return GRUB_DEV_ABSTRACTION_LUKS
;
153 return GRUB_DEV_ABSTRACTION_NONE
;
157 grub_util_pull_devmapper (const char *os_dev
)
159 struct dm_tree
*tree
;
160 struct dm_tree_node
*node
;
161 struct dm_tree_node
*child
;
163 char *lastsubdev
= NULL
;
166 uuid
= get_dm_uuid (os_dev
);
168 if (!grub_util_open_dm (os_dev
, &tree
, &node
))
174 while ((child
= dm_tree_next_child (&handle
, node
, 0)))
176 const struct dm_info
*dm
= dm_tree_node_get_info (child
);
180 subdev
= grub_find_device ("/dev", makedev (dm
->major
, dm
->minor
));
184 grub_util_pull_device (subdev
);
187 if (uuid
&& strncmp (uuid
, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
190 char *grdev
= grub_util_get_grub_dev (lastsubdev
);
195 err
= grub_cryptodisk_cheat_mount (grdev
, os_dev
);
197 grub_util_error (_("can't mount encrypted volume `%s': %s"),
198 lastsubdev
, grub_errmsg
);
208 grub_util_devmapper_part_to_disk (struct stat
*st
,
209 int *is_part
, const char *path
)
213 if (grub_util_get_dm_node_linear_info (st
->st_rdev
,
217 return grub_find_device ("/dev", makedev (major
, minor
));
220 return xstrdup (path
);
224 grub_util_get_devmapper_grub_dev (const char *os_dev
)
229 uuid
= get_dm_uuid (os_dev
);
233 switch (grub_util_get_dev_abstraction (os_dev
))
235 case GRUB_DEV_ABSTRACTION_LVM
:
238 int dashes
[] = { 0, 6, 10, 14, 18, 22, 26, 32, 38, 42, 46, 50, 54, 58};
240 grub_dev
= xmalloc (grub_strlen (uuid
) + 40);
241 optr
= grub_stpcpy (grub_dev
, "lvmid/");
242 for (i
= 0; i
< ARRAY_SIZE (dashes
) - 1; i
++)
244 memcpy (optr
, uuid
+ sizeof ("LVM-") - 1 + dashes
[i
],
245 dashes
[i
+1] - dashes
[i
]);
246 optr
+= dashes
[i
+1] - dashes
[i
];
249 optr
= stpcpy (optr
, uuid
+ sizeof ("LVM-") - 1 + dashes
[i
]);
251 grub_dev
[sizeof("lvmid/xxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx") - 1]
257 case GRUB_DEV_ABSTRACTION_LUKS
:
261 dash
= grub_strchr (uuid
+ sizeof ("CRYPT-LUKS1-") - 1, '-');
264 grub_dev
= grub_xasprintf ("cryptouuid/%s",
265 uuid
+ sizeof ("CRYPT-LUKS1-") - 1);
277 grub_util_get_vg_uuid (const char *os_dev
)
280 int dashes
[] = { 0, 6, 10, 14, 18, 22, 26, 32};
284 uuid
= get_dm_uuid (os_dev
);
288 vgid
= xmalloc (grub_strlen (uuid
));
290 for (i
= 0; i
< ARRAY_SIZE (dashes
) - 1; i
++)
292 memcpy (optr
, uuid
+ sizeof ("LVM-") - 1 + dashes
[i
],
293 dashes
[i
+1] - dashes
[i
]);
294 optr
+= dashes
[i
+1] - dashes
[i
];
304 grub_util_devmapper_cleanup (void)
311 grub_util_pull_devmapper (const char *os_dev
__attribute__ ((unused
)))
317 grub_util_devmapper_cleanup (void)
321 enum grub_dev_abstraction_types
322 grub_util_get_dm_abstraction (const char *os_dev
__attribute__ ((unused
)))
324 return GRUB_DEV_ABSTRACTION_NONE
;
328 grub_util_get_vg_uuid (const char *os_dev
__attribute__ ((unused
)))
334 grub_util_devmapper_part_to_disk (struct stat
*st
__attribute__ ((unused
)),
335 int *is_part
__attribute__ ((unused
)),
336 const char *os_dev
__attribute__ ((unused
)))
342 grub_util_get_devmapper_grub_dev (const char *os_dev
__attribute__ ((unused
)))