Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image-hd: add support for overridding optional fields of the MBR #260

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
***
Expand Down
41 changes: 36 additions & 5 deletions image-hd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -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));
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()
};

Expand Down
14 changes: 14 additions & 0 deletions test/hdimage.test
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down
17 changes: 17 additions & 0 deletions test/hole-skip-optionals.config
Original file line number Diff line number Diff line change
@@ -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)"
}
}
Loading