diff --git a/Makefile.am b/Makefile.am index 1aac4f1..e05b324 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,6 +100,7 @@ EXTRA_DIST += \ test/hdimage7.config \ test/hdimage7.fdisk \ test/hole.config \ + test/hole-skip-optionals.config \ test/hdimage-hybrid.config \ test/hdimage-hybrid.fdisk \ test/hdimage-fail1.config \ diff --git a/README.rst b/README.rst index 2ba3087..98fbacc 100644 --- a/README.rst +++ b/README.rst @@ -425,6 +425,9 @@ Options: up to the end of the last partition. This might make the file bigger. This is necessary if the image will be processed by such tools as libvirt, libguestfs or parted. +:mbr-skip-optionals: Boolean. If true, then the 6 bytes of optional fields in the MBR + are skipped, allowing an image occupying the first 446 bytes + instead of just the first 440 bytes to be written. iso *** diff --git a/image-hd.c b/image-hd.c index 5658c50..b567e9c 100644 --- a/image-hd.c +++ b/image-hd.c @@ -47,6 +47,7 @@ struct hdimage { unsigned long long gpt_location; cfg_bool_t gpt_no_backup; cfg_bool_t fill; + cfg_bool_t mbr_skip_optionals; unsigned long long file_size; }; @@ -64,9 +65,14 @@ struct mbr_partition_entry { } __attribute__((packed)); ct_assert(sizeof(struct mbr_partition_entry) == 16); -struct mbr_tail { +struct mbr_tail_optionals { uint32_t disk_signature; uint16_t copy_protect; +} __attribute__((packed)); +ct_assert(sizeof(struct mbr_tail_optionals) == 6); + +struct mbr_tail { + struct mbr_tail_optionals optionals; struct mbr_partition_entry part_entry[4]; uint16_t boot_signature; } __attribute__((packed)); @@ -141,6 +147,9 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions) struct hdimage *hd = image->handler_priv; struct mbr_tail mbr; struct partition *part; + unsigned long long mbr_offset; + const void *mbr_data; + size_t mbr_size; int ret, i = 0; if (hd->table_type == TYPE_HYBRID) { @@ -150,7 +159,7 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions) } memset(&mbr, 0, sizeof(mbr)); - memcpy(&mbr.disk_signature, &hd->disksig, sizeof(hd->disksig)); + memcpy(&mbr.optionals.disk_signature, &hd->disksig, sizeof(hd->disksig)); list_for_each_entry(part, partitions, list) { struct mbr_partition_entry *entry; @@ -192,7 +201,16 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions) mbr.boot_signature = htole16(0xaa55); - ret = insert_data(image, &mbr, imageoutfile(image), sizeof(mbr), 440); + mbr_offset = 440; + mbr_size = sizeof(mbr); + mbr_data = &mbr; + if (hd->mbr_skip_optionals) { + mbr_offset += sizeof(struct mbr_tail_optionals); + mbr_size -= sizeof(struct mbr_tail_optionals); + mbr_data = &mbr.part_entry[0]; + } + + ret = insert_data(image, mbr_data, imageoutfile(image), mbr_size, mbr_offset); if (ret) { if (hd->table_type == TYPE_HYBRID) { image_error(image, "failed to write hybrid MBR\n"); @@ -968,6 +986,7 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) hd->gpt_location = cfg_getint_suffix(cfg, "gpt-location"); hd->gpt_no_backup = cfg_getbool(cfg, "gpt-no-backup"); hd->fill = cfg_getbool(cfg, "fill"); + hd->mbr_skip_optionals = cfg_getbool(cfg, "mbr-skip-optionals"); if (is_block_device(imageoutfile(image))) { if (image->size) { @@ -1029,8 +1048,19 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) } if (hd->table_type != TYPE_NONE) { - struct partition *mbr = fake_partition("[MBR]", 512 - sizeof(struct mbr_tail), - sizeof(struct mbr_tail)); + struct partition *mbr; + unsigned long long mbr_offset; + unsigned long long mbr_size; + + mbr_offset = 512 - sizeof(struct mbr_tail); + mbr_size = sizeof(struct mbr_tail); + + if (hd->mbr_skip_optionals) { + mbr_offset += sizeof(struct mbr_tail_optionals); + mbr_size -= sizeof(struct mbr_tail_optionals); + } + + mbr = fake_partition("[MBR]", mbr_offset, mbr_size); list_add_tail(&mbr->list, &image->partitions); now = partition_end(mbr); @@ -1215,6 +1245,7 @@ static cfg_opt_t hdimage_opts[] = { CFG_STR("gpt-location", NULL, CFGF_NONE), CFG_BOOL("gpt-no-backup", cfg_false, CFGF_NONE), CFG_BOOL("fill", cfg_false, CFGF_NONE), + CFG_BOOL("mbr-skip-optionals", cfg_false, CFGF_NONE), CFG_END() }; diff --git a/test/hdimage.test b/test/hdimage.test index 61e1429..daf1341 100755 --- a/test/hdimage.test +++ b/test/hdimage.test @@ -159,6 +159,20 @@ test_expect_success "bootloader-hole5" " setup_gpt_files && OFFSET=128K run_genimage hole.config" +# Test the mbr-skip-optionals +test_expect_success "bootloader-hole6" " + rm -rf input && + mkdir input && + truncate -s 100K input/bootloader.img && + MBR_SKIP_OPTIONALS=true run_genimage hole-skip-optionals.config" + +# Test the mbr-skip-optionals +test_expect_success "bootloader-hole7" " + rm -rf input && + mkdir input && + truncate -s 100K input/bootloader.img && + MBR_SKIP_OPTIONALS=false test_must_fail run_genimage hole-skip-optionals.config" + test_expect_success hexdump "hdimage no-partition" " dd if=/dev/zero bs=1 count=100 | tr '\000' '\377' > input/block1.img && dd if=/dev/zero bs=1 count=50 | tr '\000' '\252' > input/block2.img && diff --git a/test/hole-skip-optionals.config b/test/hole-skip-optionals.config new file mode 100644 index 0000000..903c0be --- /dev/null +++ b/test/hole-skip-optionals.config @@ -0,0 +1,17 @@ +image test.hole { + hdimage { + mbr-skip-optionals = "${MBR_SKIP_OPTIONALS}" + } + + partition bootloader { + in-partition-table = false + offset = 0 + image = "bootloader.img" + } +} + +image bootloader.img { + file { + holes = "(444; 512)" + } +}