New option bits with el_torito_set_isolinux_options() and

iso_write_opts_set_system_area() to control GRUB2 patching of
boot image and MBR
This commit is contained in:
Thomas Schmitt 2013-04-13 08:38:52 +02:00
parent eb6503a8ad
commit 337bade549
7 changed files with 109 additions and 14 deletions

View File

@ -3275,7 +3275,7 @@ int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768],
memcpy(opts->system_area_data, data, 32768); memcpy(opts->system_area_data, data, 32768);
} }
if (!(flag & 4)) if (!(flag & 4))
opts->system_area_options = options & 0x3fff; opts->system_area_options = options & 0x7fff;
return ISO_SUCCESS; return ISO_SUCCESS;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2010 Thomas Schmitt * Copyright (c) 2010 - 2013 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -160,7 +160,13 @@ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
/* API */ /* API */
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag) int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag)
{ {
return bootimg->seems_boot_info_table; switch (flag & 15) {
case 0:
return bootimg->seems_boot_info_table;
case 1:
return bootimg->seems_grub2_boot_info;
}
return 0;
} }
/** /**
@ -197,14 +203,14 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
*/ */
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag) int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
{ {
bootimg->isolinux_options = (options & 0x01ff); bootimg->isolinux_options = (options & 0x03ff);
return ISO_SUCCESS; return ISO_SUCCESS;
} }
/* API */ /* API */
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag) int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
{ {
return bootimg->isolinux_options & 0x01ff; return bootimg->isolinux_options & 0x03ff;
} }
/* API */ /* API */
@ -1096,7 +1102,7 @@ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
} }
/** /**
* Patch an isolinux boot image. * Patch an El Torito boot image by a boot info table.
* *
* @return * @return
* 1 on success, 0 error (but continue), < 0 error * 1 on success, 0 error (but continue), < 0 error
@ -1117,6 +1123,27 @@ int patch_boot_info_table(uint8_t *buf, Ecma119Image *t,
return ret; return ret;
} }
/**
* Patch a GRUB2 El Torito boot image.
*/
static
int patch_grub2_boot_image(uint8_t *buf, Ecma119Image *t,
size_t imgsize, int idx,
size_t pos, int offst)
{
uint64_t blk;
if (imgsize < pos + 8)
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
"Isolinux image too small for GRUB2. Will not patch it.");
blk = ((uint64_t) t->bootsrc[idx]->sections[0].block) * 4 + offst;
iso_lsb((buf + pos), blk & 0xffffffff, 4);
iso_lsb((buf + pos + 4), blk >> 32, 4);
return ISO_SUCCESS;
}
/* Patch the boot images if indicated */ /* Patch the boot images if indicated */
int iso_patch_eltoritos(Ecma119Image *t) int iso_patch_eltoritos(Ecma119Image *t)
{ {
@ -1130,7 +1157,7 @@ int iso_patch_eltoritos(Ecma119Image *t)
return ISO_SUCCESS; return ISO_SUCCESS;
for (idx = 0; idx < t->catalog->num_bootimages; idx++) { for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01)) if (!(t->catalog->bootimages[idx]->isolinux_options & 0x201))
continue; continue;
original = t->bootsrc[idx]->stream; original = t->bootsrc[idx]->stream;
size = (size_t) iso_stream_get_size(original); size = (size_t) iso_stream_get_size(original);
@ -1154,9 +1181,20 @@ int iso_patch_eltoritos(Ecma119Image *t)
} }
/* ok, patch the read buffer */ /* ok, patch the read buffer */
ret = patch_boot_info_table(buf, t, size, idx); if (t->catalog->bootimages[idx]->isolinux_options & 0x200) {
if (ret < 0) { /* GRUB2 boot provisions */
return ret; ret = patch_grub2_boot_image(buf, t, size, idx,
Libisofs_grub2_elto_patch_poS,
Libisofs_grub2_elto_patch_offsT);
if (ret < 0)
return ret;
}
/* Must be done as last patching */
if (t->catalog->bootimages[idx]->isolinux_options & 0x01) {
/* Boot Info Table */
ret = patch_boot_info_table(buf, t, size, idx);
if (ret < 0)
return ret;
} }
/* replace the original stream with a memory stream that reads from /* replace the original stream with a memory stream that reads from

View File

@ -58,6 +58,7 @@ struct el_torito_boot_image {
* Whether the boot image seems to contain a boot_info_table * Whether the boot image seems to contain a boot_info_table
*/ */
unsigned int seems_boot_info_table:1; unsigned int seems_boot_info_table:1;
unsigned int seems_grub2_boot_info:1;
/** /**
* isolinux options * isolinux options
* bit 0 -> whether to patch image * bit 0 -> whether to patch image
@ -155,4 +156,12 @@ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
*/ */
int iso_patch_eltoritos(Ecma119Image *t); int iso_patch_eltoritos(Ecma119Image *t);
/* Parameters for patch_grub2_boot_image()
Might later become variables in struct el_torito_boot_image.
*/
#define Libisofs_grub2_elto_patch_poS (512 * 5 - 12)
#define Libisofs_grub2_elto_patch_offsT 5
#endif /* LIBISO_ELTORITO_H */ #endif /* LIBISO_ELTORITO_H */

View File

@ -3375,13 +3375,14 @@ static
int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts, int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts,
IsoDataSource *src, uint32_t iso_image_size, int flag) IsoDataSource *src, uint32_t iso_image_size, int flag)
{ {
int i, ret, section_count, todo, chunk; int i, j, ret, section_count, todo, chunk;
uint32_t img_lba, img_size, boot_pvd_found, image_pvd, alleged_size; uint32_t img_lba, img_size, boot_pvd_found, image_pvd, alleged_size;
struct iso_file_section *sections = NULL; struct iso_file_section *sections = NULL;
struct el_torito_boot_image *boot; struct el_torito_boot_image *boot;
uint8_t *boot_image_buf = NULL, boot_info_found[16], *buf = NULL; uint8_t *boot_image_buf = NULL, boot_info_found[16], *buf = NULL;
IsoStream *stream = NULL; IsoStream *stream = NULL;
IsoFile *boot_file; IsoFile *boot_file;
uint64_t blk;
if (image->bootcat == NULL) if (image->bootcat == NULL)
{ret = ISO_SUCCESS; goto ex;} {ret = ISO_SUCCESS; goto ex;}
@ -3390,6 +3391,7 @@ int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts,
boot = image->bootcat->bootimages[i]; boot = image->bootcat->bootimages[i];
boot_file = boot->image; boot_file = boot->image;
boot->seems_boot_info_table = 0; boot->seems_boot_info_table = 0;
boot->seems_grub2_boot_info = 0;
img_size = iso_file_get_size(boot_file); img_size = iso_file_get_size(boot_file);
if (img_size > Libisofs_boot_image_max_sizE || img_size < 64) if (img_size > Libisofs_boot_image_max_sizE || img_size < 64)
continue; continue;
@ -3455,6 +3457,16 @@ int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts,
goto ex; goto ex;
if (memcmp(boot_image_buf + 8, boot_info_found, 16) == 0) if (memcmp(boot_image_buf + 8, boot_info_found, 16) == 0)
boot->seems_boot_info_table = 1; boot->seems_boot_info_table = 1;
if (img_size >= Libisofs_grub2_elto_patch_poS + 8) {
blk = 0;
for (j = Libisofs_grub2_elto_patch_poS + 7;
j >= Libisofs_grub2_elto_patch_poS; j--)
blk = (blk << 8) | boot_image_buf[j];
if (blk == img_lba * 4 + Libisofs_grub2_elto_patch_offsT)
boot->seems_grub2_boot_info = 1;
}
free(boot_image_buf); free(boot_image_buf);
boot_image_buf = NULL; boot_image_buf = NULL;
} }

View File

@ -2191,6 +2191,13 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* 1 = CHRP: A single MBR partition of type 0x96 covers the * 1 = CHRP: A single MBR partition of type 0x96 covers the
* ISO image. Not compatible with any other feature * ISO image. Not compatible with any other feature
* which needs to have own MBR partition entries. * which needs to have own MBR partition entries.
* bit14= Only with System area type 0 = MBR
* GRUB2 boot provisions:
* @since 1.3.0
* Patch system area at byte 92 to 99 with 512-block address + 1
* of the first boot image file. Little-endian 8-byte.
* Should be combined with options bit0.
* Will not be in effect if options bit1 is set.
* @param flag * @param flag
* bit0 = invalidate any attached system area data. Same as data == NULL * bit0 = invalidate any attached system area data. Same as data == NULL
* (This re-activates eventually loaded image System Area data. * (This re-activates eventually loaded image System Area data.
@ -3465,9 +3472,15 @@ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]);
* @param bootimg * @param bootimg
* The image to inquire * The image to inquire
* @param flag * @param flag
* Reserved for future usage, set to 0. * Bitfield for control purposes:
* bit0 - bit3= mode
* 0 = inquire for classic boot info table as described in man mkisofs
* @since 0.6.32
* 1 = inquire for GRUB2 boot info as of bit9 of options of
* el_torito_set_isolinux_options()
* @since 1.3.0
* @return * @return
* 1 = seems to contain oot info table , 0 = quite surely not * 1 = seems to contain the inquired boot info, 0 = quite surely not
* @since 0.6.32 * @since 0.6.32
*/ */
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag); int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
@ -3531,6 +3544,11 @@ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
* mentioned. The ISOLINUX MBR must look suitable or else an error * mentioned. The ISOLINUX MBR must look suitable or else an error
* event will happen at image generation time. * event will happen at image generation time.
* @since 1.2.4 * @since 1.2.4
* bit9= GRUB2 boot info
* Patch the boot image file at byte 1012 with the 512-block
* address + 2. Two little endian 32-bit words. Low word first.
* This is combinable with bit0.
* @since 1.3.0
* @param flag * @param flag
* Reserved for future usage, set to 0. * Reserved for future usage, set to 0.
* @return * @return

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2008 Vreixo Formoso * Copyright (c) 2008 Vreixo Formoso
* Copyright (c) 2010 - 2012 Thomas Schmitt * Copyright (c) 2010 - 2013 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -1417,6 +1417,8 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
int first_partition = 1, last_partition = 4, apm_flag, part_type; int first_partition = 1, last_partition = 4, apm_flag, part_type;
int gpt_count = 0, gpt_idx[128], apm_count = 0; int gpt_count = 0, gpt_idx[128], apm_count = 0;
uint32_t img_blocks; uint32_t img_blocks;
uint64_t blk;
uint8_t *wpt;
if ((t == NULL) || (buf == NULL)) { if ((t == NULL) || (buf == NULL)) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
@ -1607,6 +1609,15 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
return ret; return ret;
} }
if (sa_type == 0 && (t->system_area_options & 0x4000) && !do_isohybrid) {
/* Patch MBR for GRUB2 */
blk = t->bootsrc[0]->sections[0].block * 4 +
Libisofs_grub2_mbr_patch_offsT;
wpt = buf + Libisofs_grub2_mbr_patch_poS;
for (i = 0; i < 8; i++)
wpt[i] = blk >> (i * 8);
}
return ISO_SUCCESS; return ISO_SUCCESS;
} }

View File

@ -266,4 +266,11 @@ int gpt_tail_writer_create(Ecma119Image *target);
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */ /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
void iso_ascii_utf_16le(uint8_t gap_name[72]); void iso_ascii_utf_16le(uint8_t gap_name[72]);
/* Parameters of MBR patching for GRUB2
Might later become variables in Ecma119Image
*/
#define Libisofs_grub2_mbr_patch_poS 0x1b0
#define Libisofs_grub2_mbr_patch_offsT 3
#endif /* SYSTEM_AREA_H_ */ #endif /* SYSTEM_AREA_H_ */