1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-07 18:27:04 +03:00

nspawn: support dissecting GPT images that contain only a single generic linux partition

This should allow running Ubuntu UEFI GPT Images with nspawn,
unmodified.
This commit is contained in:
Lennart Poettering 2015-01-19 20:22:58 +01:00
parent ec5cb56ee1
commit f6c51a8136
2 changed files with 57 additions and 38 deletions

View File

@ -2618,7 +2618,8 @@ static int wait_for_block_device(struct udev *udev, dev_t devnum, struct udev_de
#define PARTITION_TABLE_BLURB \
"Note that the disk image needs to either contain only a single MBR partition of\n" \
"type 0x83 that is marked bootable, or follow\n" \
"type 0x83 that is marked bootable, or a sinlge GPT partition of type" \
"0FC63DAF-8483-4772-8E79-3D69D8477DE4 or follow\n" \
" http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/\n" \
"to be bootable with systemd-nspawn."
@ -2637,19 +2638,18 @@ static int dissect_image(
#ifdef GPT_ROOT_SECONDARY
int secondary_root_nr = -1;
#endif
_cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL;
_cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *generic = NULL;
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
_cleanup_udev_unref_ struct udev *udev = NULL;
struct udev_list_entry *first, *item;
bool home_rw = true, root_rw = true, secondary_root_rw = true, srv_rw = true;
bool home_rw = true, root_rw = true, secondary_root_rw = true, srv_rw = true, generic_rw = true;
const char *pttype = NULL;
blkid_partlist pl;
struct stat st;
int r;
bool is_gpt, is_mbr;
bool is_gpt, is_mbr, multiple_generic = false;
assert(fd >= 0);
assert(root_device);
@ -2769,10 +2769,6 @@ static int dissect_image(
continue;
flags = blkid_partition_get_flags(pp);
if (is_gpt && (flags & GPT_FLAG_NO_AUTO))
continue;
if (is_mbr && (flags != 0x80)) /* Bootable flag */
continue;
nr = blkid_partition_get_partno(pp);
if (nr < 0)
@ -2782,6 +2778,9 @@ static int dissect_image(
sd_id128_t type_id;
const char *stype;
if (flags & GPT_FLAG_NO_AUTO)
continue;
stype = blkid_partition_get_type_string(pp);
if (!stype)
continue;
@ -2841,48 +2840,41 @@ static int dissect_image(
return log_oom();
}
#endif
else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
if (generic)
multiple_generic = true;
else {
generic_rw = !(flags & GPT_FLAG_READ_ONLY);
r = free_and_strdup(&generic, node);
if (r < 0)
return log_oom();
}
}
} else if (is_mbr) {
int type;
if (flags != 0x80) /* Bootable flag */
continue;
type = blkid_partition_get_type(pp);
if (type != 0x83) /* Linux partition */
continue;
/* Note that there's a certain, intended
* asymmetry here: while for GPT we simply
* take the first valid partition and ignore
* all others of the same type, for MBR we
* fail if there are multiple suitable
* partitions. This is because the GPT
* partition types are defined by us, and
* hence we can define their lookup semantics,
* while for the MBR logic we reuse existing
* definitions, and simply don't want to make
* out the situation. */
if (generic)
multiple_generic = true;
else {
generic_rw = true;
if (root) {
log_error("Identified multiple bootable Linux 0x83 partitions on\n"
" %s\n"
PARTITION_TABLE_BLURB, arg_image);
return -EINVAL;
r = free_and_strdup(&root, node);
if (r < 0)
return log_oom();
}
root_nr = nr;
r = free_and_strdup(&root, node);
if (r < 0)
return log_oom();
}
}
if (!root && !secondary_root) {
log_error("Failed to identify root partition in disk image\n"
" %s\n"
PARTITION_TABLE_BLURB, arg_image);
return -EINVAL;
}
if (root) {
*root_device = root;
root = NULL;
@ -2895,6 +2887,31 @@ static int dissect_image(
*root_device_rw = secondary_root_rw;
*secondary = true;
} else if (generic) {
/* There were no partitions with precise meanings
* around, but we found generic partitions. In this
* case, if there's only one, we can go ahead and boot
* it, otherwise we bail out, because we really cannot
* make any sense of it. */
if (multiple_generic) {
log_error("Identified multiple bootable Linux partitions on\n"
" %s\n"
PARTITION_TABLE_BLURB, arg_image);
return -EINVAL;
}
*root_device = generic;
generic = NULL;
*root_device_rw = generic_rw;
*secondary = false;
} else {
log_error("Failed to identify root partition in disk image\n"
" %s\n"
PARTITION_TABLE_BLURB, arg_image);
return -EINVAL;
}
if (home) {

View File

@ -57,3 +57,5 @@
* just because we saw no point in defining any other values here. */
#define GPT_FLAG_READ_ONLY (1ULL << 60)
#define GPT_FLAG_NO_AUTO (1ULL << 63)
#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4)