From 872b5c6c67ec5678c45092dc42538a0418eb3053 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Fri, 1 Jan 2016 18:17:40 +0100 Subject: [PATCH] New bit15 with options of iso_write_opts_set_system_area() to enforce MBR bootable/active flag. --- libisofs/ecma119.c | 2 +- libisofs/fs_image.c | 7 ++- libisofs/libisofs.h | 13 +++-- libisofs/system_area.c | 108 ++++++++++++++++++----------------------- 4 files changed, 62 insertions(+), 68 deletions(-) diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 4429e91..1a8c3bc 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -3990,7 +3990,7 @@ int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768], opts->system_area_size = 32768; } if (!(flag & 4)) - opts->system_area_options = options & 0x7fff; + opts->system_area_options = options & 0xffff; return ISO_SUCCESS; } diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index ee68609..e55ac7e 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -3940,6 +3940,7 @@ int iso_analyze_mbr(IsoImage *image, IsoDataSource *src, int flag) { int sub_type = 2, ret, is_isohybrid = 0, is_grub2_mbr = 0; int is_protective_label = 0; + uint64_t part2_start; char *sad; struct iso_imported_sys_area *sai; struct iso_mbr_partition_request *part; @@ -3969,8 +3970,12 @@ int iso_analyze_mbr(IsoImage *image, IsoDataSource *src, int flag) if (sai->mbr_req_count >= 1 && !is_isohybrid) { part = sai->mbr_req[0]; + part2_start = 0; + if (sai->mbr_req_count >= 2) + part2_start = sai->mbr_req[1]->start_block; if (part->start_block == 1 && - part->block_count + 1 == ((uint64_t) sai->image_size) * 4) { + (part->block_count + 1 == ((uint64_t) sai->image_size) * 4 || + part->block_count + 1 == part2_start)) { /* libisofs protective msdos label for GRUB2 */ is_protective_label = 1; sub_type = 0; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index fad3649..59d930b 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -2215,8 +2215,9 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size); * @since 1.2.6 * bit10-13= System area sub type * @since 1.2.4 - * With type 0 = MBR: - * Gets overridden by bit0 and bit1. + * With type 0: + * bit0 ... MBR with partition start at block 1 + * bit1 ... ISOLINUX isohybrid MBR * 0 = no particular sub type, use unaltered * 1 = CHRP: A single MBR partition of type 0x96 covers the * ISO image. Not compatible with any other feature @@ -2228,8 +2229,12 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size); * Patch system area at byte 0x1b0 to 0x1b7 with * (512-block address + 4) of the first boot image file. * Little-endian 8-byte. - * Should be combined with options bit0. + * Is normally combined with options bit0. * Will not be in effect if options bit1 is set. + * bit15= Only with System area type MBR but not with CHRP + * Enforce MBR "bootable/active" flag. In worst case by dummy + * partition of type 0x00 which occupies block 0. + * @since 1.4.4 * @param flag * bit0 = invalidate any attached system area data. Same as data == NULL * (This re-activates eventually loaded image System Area data. @@ -3403,7 +3408,7 @@ int iso_image_get_pvd_times(IsoImage *image, * @param image_path * The absolute path of a IsoFile to be used as default boot image. ->>> or --interval:appended_partition_$number... +>>> or --interval:appended_partition_$number_start_$start_size_$size:... * @param type * The boot media type. This can be one of 3 types: diff --git a/libisofs/system_area.c b/libisofs/system_area.c index ba613a1..5d9fad0 100644 --- a/libisofs/system_area.c +++ b/libisofs/system_area.c @@ -1749,38 +1749,33 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf) } -#ifdef Libisofs_protective_msdos_plus_boot_dummY - +/* Add a dummy MBR partition of type 0 with boot flag */ static void iso_dummy_mbr_partition(uint8_t *buf, int mode) { - /* Add a dummy partition of type 0 with boot flag */ - if (mode == 0) { - /* Start LBA 0, block count 1 */ - buf[446 + 16 + 0] = 0x80; /* bootable */ - buf[446 + 16 + 1] = 0x00; /* start head */ - buf[446 + 16 + 2] = 0x01; /* start sector */ - buf[446 + 16 + 3] = 0x00; /* start cylinder */ - buf[446 + 16 + 4] = 0x00; /* partition type */ - buf[446 + 16 + 5] = 0x00; /* end head */ - buf[446 + 16 + 6] = 0x01; /* last sector */ - buf[446 + 16 + 7] = 0x00; /* end cylinder */ - buf[446 + 16 + 8] = 0x00; /* start LBA */ - buf[446 + 16 + 9] = 0x00; - buf[446 + 16 + 10] = 0x00; - buf[446 + 16 + 11] = 0x00; - buf[446 + 16 + 12] = 0x01; /* block count */ - buf[446 + 16 + 13] = 0x00; - buf[446 + 16 + 14] = 0x00; - buf[446 + 16 + 15] = 0x00; - } else { - /* copy partition 1 to 2, set boot flag and type 0x00 */ - memcpy(buf + 446 + 16, buf + 446, 16); - buf[446 + 16 + 0] = 0x80; /* bootable */ - buf[446 + 16 + 4] = 0x00; /* partition type */ + int i; + /* bootable , start 0/0/1, type 0x00, end 0/0/1, + start LBA 0, block count 1 */ + static uint8_t dummy_entry[16] = { + 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; + + for (i = 0; i < 4; i++) { + if (buf[446 + 16 * i + 4] == 0x00) { + memcpy(buf + 446 + 16 * i, dummy_entry, 16); + return; + } } + /* Abundance of 0xee and 0xef partitions. No other one free. */ + for (i = 0; i < 4; i++) { + if (buf[446 + 16 * i + 4] != 0xef) { + buf[446 + 16 * i] |= 0x80; + return; + } + } + i = 3; + buf[446 + 16 * i] |= 0x80; } -#endif /* Libisofs_protective_msdos_plus_boot_dummY */ int iso_write_system_area(Ecma119Image *t, uint8_t *buf) { @@ -2077,24 +2072,6 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf) #ifdef Libisofs_mjg_boot_for_grub2 - - if (buf[446 + 4] != 0x00) { - if (buf[446 + 4] != 0xef && buf[446 + 4] != 0xee) - buf[446] |= 0x80; - -#ifdef Libisofs_protective_msdos_plus_boot_dummY - - else if (buf[446 + 16 + 4] == 0x00 && (buf[446 + 16] & 0x80) == 0) -#ifdef Libisofs_pmpbd_on_lba0 - iso_dummy_mbr_partition(buf, 0); -#else - iso_dummy_mbr_partition(buf, 1); -#endif /* ! Libisofs_pmpbd_on_lba0 */ - -#endif - - } - /* Prevent MBR partition type 0xee */ if (sa_type == 0 && ((t->system_area_options & 3) || risk_of_ee) && (t->have_appended_partitions || t->gpt_req_count == 0)) { @@ -2120,27 +2097,34 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf) } } -#ifdef Libisofs_protective_msdos_plus_boot_dummY - - if (sa_type == 0 && (t->system_area_options & 3) == 1 && - buf[446 + 4] == 0xee && buf[446] == 0x00) { - for (i = 446 + 16 ; i < 510; i++) - if(buf[i]) + if (sa_type == 0 && ( + (t->system_area_options & 3) || + (t->system_area_options & (1 << 14)) || + (((t->system_area_options >> 2) & 0x3f) == 2 && + (t->system_area_options & (1 << 15))) + )) { + /* This is an MBR which shall have a bootable/active flag + protective-msdos-label, isohybrid, grub2-mbr, mbr-force-bootable + */ + for (i = 0; i < 4; i++) + if (buf[446 + 16 * i] & 0x80) break; - if (i >= 510) { - /* Add a dummy partition of type 0 with boot flag */ - -#ifdef Libisofs_pmpbd_on_lba0 - iso_dummy_mbr_partition(buf, 0); -#else - iso_dummy_mbr_partition(buf, 1); -#endif /* ! Libisofs_pmpbd_on_lba0 */ - + if (i >= 4) { /* no bootable/active flag set yet */ + for (i = 0; i < 4; i++) { + if (buf[446 + 16 * i + 4] != 0x00 && + buf[446 + 16 * i + 4] != 0xee && + buf[446 + 16 * i + 4] != 0xef) { + buf[446 + 16 * i] |= 0x80; + break; + } + } + if (i >= 4) { /* still no bootable/active flag set */ + if (t->system_area_options & (1 << 15)) /* Force it */ + iso_dummy_mbr_partition(buf, 0); + } } } -#endif /* Libisofs_protective_msdos_plus_boot_dummY */ - return ISO_SUCCESS; }