Making an educated guess whether the boot images contain a boot info table.
New API call el_torito_seems_boot_info_table() publishes this guess.
This commit is contained in:
parent
3d9367d52a
commit
e4cf93665a
@ -153,8 +153,14 @@ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag)
|
||||
{
|
||||
return bootimg->seems_boot_info_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* Specifies that this image needs to be patched. This involves the writing
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
@ -173,7 +179,7 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
|
||||
* bitmask style flag. The following values are defined:
|
||||
*
|
||||
* bit 0 -> 1 to path the image, 0 to not
|
||||
* Patching the image involves the writting of a 56 bytes
|
||||
* Patching the image involves the writing of a 56 bytes
|
||||
* boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified. This is needed
|
||||
* to allow isolinux images to be bootable.
|
||||
@ -405,6 +411,7 @@ int create_image(IsoImage *image, const char *image_path,
|
||||
boot->image = (IsoFile*)imgfile;
|
||||
iso_node_ref(imgfile); /* get our ref */
|
||||
boot->bootable = 1;
|
||||
boot->seems_boot_info_table = 0;
|
||||
boot->isolinux_options = 0;
|
||||
boot->type = boot_media_type;
|
||||
boot->partition_type = partition_type;
|
||||
@ -677,10 +684,12 @@ void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
|
||||
image = cat->bootimages[i];
|
||||
if (image == NULL)
|
||||
continue;
|
||||
iso_node_unref((IsoNode*)image->image);
|
||||
if ((IsoNode*)image->image != NULL)
|
||||
iso_node_unref((IsoNode*)image->image);
|
||||
free(image);
|
||||
}
|
||||
iso_node_unref((IsoNode*)cat->node);
|
||||
if ((IsoNode*)cat->node != NULL)
|
||||
iso_node_unref((IsoNode*)cat->node);
|
||||
free(cat);
|
||||
}
|
||||
|
||||
@ -981,6 +990,50 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
|
||||
|
||||
/******************* EL-TORITO WRITER *******************************/
|
||||
|
||||
/**
|
||||
* Insert boot info table content into buf.
|
||||
*
|
||||
* @return
|
||||
* 1 on success, 0 error (but continue), < 0 error
|
||||
*/
|
||||
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
||||
uint32_t boot_lba, uint32_t imgsize)
|
||||
{
|
||||
struct boot_info_table *info;
|
||||
uint32_t checksum;
|
||||
uint32_t offset;
|
||||
|
||||
info = (struct boot_info_table *) (buf + 8);
|
||||
if (imgsize < 64)
|
||||
return ISO_ISOLINUX_CANT_PATCH;
|
||||
|
||||
/* compute checksum, as the the sum of all 32 bit words in boot image
|
||||
* from offset 64 */
|
||||
checksum = 0;
|
||||
offset = 64;
|
||||
|
||||
while (offset <= imgsize - 4) {
|
||||
checksum += iso_read_lsb(buf + offset, 4);
|
||||
offset += 4;
|
||||
}
|
||||
if (offset != imgsize) {
|
||||
/*
|
||||
* file length not multiple of 4
|
||||
* empty space in isofs is padded with zero;
|
||||
* assume same for last dword
|
||||
*/
|
||||
checksum += iso_read_lsb(buf + offset, imgsize - offset);
|
||||
}
|
||||
|
||||
/*memset(info, 0, sizeof(struct boot_info_table));*/
|
||||
iso_lsb(info->bi_pvd, pvd_lba, 4);
|
||||
iso_lsb(info->bi_file, boot_lba, 4);
|
||||
iso_lsb(info->bi_length, imgsize, 4);
|
||||
iso_lsb(info->bi_csum, checksum, 4);
|
||||
memset(buf + 24, 0, 40);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch an isolinux boot image.
|
||||
*
|
||||
@ -990,6 +1043,24 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
|
||||
static
|
||||
int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
|
||||
{
|
||||
|
||||
/* >>> ts B00428 BOOT : make this the default case */
|
||||
#define Libisofs_new_patch_boot_imagE 1
|
||||
#ifdef Libisofs_new_patch_boot_imagE
|
||||
|
||||
int ret;
|
||||
|
||||
if (imgsize < 64) {
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Isolinux image too small. We won't patch it.");
|
||||
}
|
||||
ret = make_boot_info_table(buf, t->ms_block + (uint32_t) 16,
|
||||
t->bootsrc[idx]->sections[0].block,
|
||||
(uint32_t) imgsize);
|
||||
return ret;
|
||||
|
||||
#else /* Libisofs_new_patch_boot_imagE */
|
||||
|
||||
struct boot_info_table *info;
|
||||
uint32_t checksum;
|
||||
size_t offset;
|
||||
@ -1024,7 +1095,11 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
|
||||
iso_lsb(info->bi_file, t->bootsrc[idx]->sections[0].block, 4);
|
||||
iso_lsb(info->bi_length, imgsize, 4);
|
||||
iso_lsb(info->bi_csum, checksum, 4);
|
||||
memset(buf + 24, 0, 40);
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#endif /* ! Libisofs_new_patch_boot_imagE */
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
@ -1054,6 +1129,10 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
continue;
|
||||
original = t->bootsrc[idx]->stream;
|
||||
size = (size_t) iso_stream_get_size(original);
|
||||
|
||||
/* >>> BOOT ts B00428 :
|
||||
check whether size is not too large for buffering */;
|
||||
|
||||
buf = calloc(1, size);
|
||||
if (buf == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
@ -48,6 +48,10 @@ struct el_torito_boot_image {
|
||||
IsoFile *image;
|
||||
|
||||
unsigned int bootable:1; /**< If the entry is bootable. */
|
||||
/**
|
||||
* Whether the boot image seems to contain a boot_info_table
|
||||
*/
|
||||
unsigned int seems_boot_info_table:1;
|
||||
/**
|
||||
* isolinux options
|
||||
* bit 0 -> whether to patch image
|
||||
@ -126,4 +130,14 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src);
|
||||
*/
|
||||
int eltorito_writer_create(Ecma119Image *target);
|
||||
|
||||
/**
|
||||
* Insert boot info table content into buf.
|
||||
*
|
||||
* @return
|
||||
* 1 on success, 0 error (but continue), < 0 error
|
||||
*/
|
||||
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
||||
uint32_t boot_lba, uint32_t imgsize);
|
||||
|
||||
|
||||
#endif /* LIBISO_ELTORITO_H */
|
||||
|
@ -2121,19 +2121,15 @@ int read_root_susp_entries(_ImageFsData *data, uint32_t block)
|
||||
}
|
||||
|
||||
static
|
||||
int read_pvm(_ImageFsData *data, uint32_t block)
|
||||
int read_pvd_block(IsoDataSource *src, uint32_t block, uint8_t *buffer,
|
||||
uint32_t *image_size)
|
||||
{
|
||||
int ret;
|
||||
struct ecma119_pri_vol_desc *pvm;
|
||||
struct ecma119_dir_record *rootdr;
|
||||
uint8_t buffer[BLOCK_SIZE];
|
||||
|
||||
/* read PVM */
|
||||
ret = data->src->read_block(data->src, block, buffer);
|
||||
if (ret < 0) {
|
||||
ret = src->read_block(src, block, buffer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pvm = (struct ecma119_pri_vol_desc *)buffer;
|
||||
|
||||
/* sanity checks */
|
||||
@ -2143,8 +2139,24 @@ int read_pvm(_ImageFsData *data, uint32_t block)
|
||||
|
||||
return ISO_WRONG_PVD;
|
||||
}
|
||||
if (image_size != NULL)
|
||||
*image_size = iso_read_bb(pvm->vol_space_size, 4, NULL);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int read_pvm(_ImageFsData *data, uint32_t block)
|
||||
{
|
||||
int ret;
|
||||
struct ecma119_pri_vol_desc *pvm;
|
||||
struct ecma119_dir_record *rootdr;
|
||||
uint8_t buffer[BLOCK_SIZE];
|
||||
|
||||
ret = read_pvd_block(data->src, block, buffer, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* ok, it is a valid PVD */
|
||||
pvm = (struct ecma119_pri_vol_desc *)buffer;
|
||||
|
||||
/* fill volume attributes */
|
||||
/* TODO take care of input charset */
|
||||
@ -2206,6 +2218,7 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
|
||||
struct el_torito_section_entry *entry; /* also usable as default_entry */
|
||||
unsigned char buffer[BLOCK_SIZE];
|
||||
|
||||
data->num_bootimgs = 0;
|
||||
ret = data->src->read_block(data->src, block, buffer);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@ -2281,7 +2294,6 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
|
||||
}
|
||||
}
|
||||
after_bootblocks:;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -3005,6 +3017,105 @@ boot_fs_cleanup: ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** ??? ts B00428 : should the max size become public ? */
|
||||
#define Libisofs_boot_image_max_sizE (4096*1024)
|
||||
|
||||
/** ts B00428 BOOT : perform boot-info-table detection
|
||||
*/
|
||||
static
|
||||
int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts,
|
||||
IsoDataSource *src, uint32_t iso_image_size, int flag)
|
||||
{
|
||||
int i, ret, section_count, todo, chunk;
|
||||
uint32_t img_lba, img_size, boot_pvd_found, image_pvd, alleged_size;
|
||||
struct iso_file_section *sections = NULL;
|
||||
struct el_torito_boot_image *boot;
|
||||
uint8_t *boot_image_buf = NULL, boot_info_found[16], buf[BLOCK_SIZE];
|
||||
IsoStream *stream = NULL;
|
||||
IsoFile *boot_file;
|
||||
|
||||
if (image->bootcat == NULL)
|
||||
return ISO_SUCCESS;
|
||||
for (i = 0; i < image->bootcat->num_bootimages; i++) {
|
||||
boot = image->bootcat->bootimages[i];
|
||||
boot_file = boot->image;
|
||||
boot->seems_boot_info_table = 0;
|
||||
img_size = iso_file_get_size(boot_file);
|
||||
if (img_size > Libisofs_boot_image_max_sizE || img_size < 64)
|
||||
continue;
|
||||
img_lba = 0;
|
||||
sections = NULL;
|
||||
ret = iso_file_get_old_image_sections(boot_file,
|
||||
§ion_count, §ions, 0);
|
||||
if (ret == 1 && section_count > 0)
|
||||
img_lba = sections[0].block;
|
||||
if (sections != NULL) {
|
||||
free(sections);
|
||||
sections = NULL;
|
||||
}
|
||||
if(img_lba == 0)
|
||||
continue;
|
||||
|
||||
boot_image_buf = calloc(1, img_size);
|
||||
if (boot_image_buf == NULL) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
stream = iso_file_get_stream(boot_file);
|
||||
ret = iso_stream_open(stream);
|
||||
if (ret < 0) {
|
||||
stream = NULL;
|
||||
goto ex;
|
||||
}
|
||||
for (todo = img_size; todo > 0; ) {
|
||||
if (todo > BLOCK_SIZE)
|
||||
chunk = BLOCK_SIZE;
|
||||
else
|
||||
chunk = todo;
|
||||
ret = iso_stream_read(stream, boot_image_buf + (img_size - todo),
|
||||
chunk);
|
||||
if (ret != chunk) {
|
||||
ret = (ret < 0) ? ret : ISO_FILE_READ_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
todo -= chunk;
|
||||
}
|
||||
iso_stream_close(stream);
|
||||
stream = NULL;
|
||||
|
||||
memcpy(boot_info_found, boot_image_buf + 8, 16);
|
||||
boot_pvd_found = iso_read_lsb(boot_info_found, 4);
|
||||
image_pvd = (uint32_t) (opts->block + 16);
|
||||
|
||||
/* Accomodate to eventually relocated superblock */
|
||||
if (image_pvd != boot_pvd_found &&
|
||||
image_pvd == 16 && boot_pvd_found < iso_image_size) {
|
||||
/* Check whether there is a PVD at boot_pvd_found
|
||||
and whether it bears the same image size
|
||||
*/
|
||||
ret = read_pvd_block(src, boot_pvd_found, buf, &alleged_size);
|
||||
if (ret == 1 &&
|
||||
alleged_size + boot_pvd_found == iso_image_size + image_pvd)
|
||||
image_pvd = boot_pvd_found;
|
||||
}
|
||||
|
||||
ret = make_boot_info_table(boot_image_buf, image_pvd,
|
||||
img_lba, img_size);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (memcmp(boot_image_buf + 8, boot_info_found, 16) == 0)
|
||||
boot->seems_boot_info_table = 1;
|
||||
free(boot_image_buf);
|
||||
boot_image_buf = NULL;
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (boot_image_buf != NULL)
|
||||
free(boot_image_buf);
|
||||
if (stream != NULL)
|
||||
iso_stream_close(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
struct iso_read_opts *opts,
|
||||
@ -3140,6 +3251,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto import_revert;
|
||||
}
|
||||
boot_image->image = NULL;
|
||||
boot_image->bootable = data->boot_flags[idx] & 1;
|
||||
boot_image->type = data->media_types[idx];
|
||||
boot_image->partition_type = data->partition_types[idx];
|
||||
@ -3314,6 +3426,11 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
|
||||
#endif /* Libisofs_with_checksumS */
|
||||
|
||||
/* ts B00428 */
|
||||
ret = iso_image_eval_boot_info_table(image, opts, src, data->nblocks, 0);
|
||||
if (ret < 0)
|
||||
goto import_revert;
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
goto import_cleanup;
|
||||
|
||||
|
@ -2631,35 +2631,41 @@ int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]);
|
||||
*/
|
||||
int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]);
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writing
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
* Makes a guess whether the boot image was patched by a boot information
|
||||
* table. It is advisable to patch such boot images if their content gets
|
||||
* copied to a new location. See el_torito_set_isolinux_options().
|
||||
* Note: The reply can be positive only if the boot image was imported
|
||||
* from an existing ISO image.
|
||||
*
|
||||
* @since 0.6.2
|
||||
* @deprecated Use el_torito_set_isolinux_options() instead
|
||||
* @param bootimg
|
||||
* The image to inquire
|
||||
* @return
|
||||
* 1 = seems to contain oot info table , 0 = quite surely not
|
||||
* @since 0.6.32
|
||||
*/
|
||||
void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
|
||||
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
|
||||
|
||||
/**
|
||||
* Specifies options for ISOLINUX or GRUB boot images. This should only be used
|
||||
* if the type of boot image is known.
|
||||
*
|
||||
* Regrettably there is no unambigous way to detect the presence of a boot
|
||||
* info table in a boot image or the relation of a boot image to the System
|
||||
* Area and its eventual MBR.
|
||||
*
|
||||
* @param options
|
||||
* bitmask style flag. The following values are defined:
|
||||
*
|
||||
* bit 0 -> 1 to patch the boot info table of the boot image.
|
||||
* 1 does the same as mkisofs option -boot-info-table.
|
||||
* Needed for ISOLINUX and for GRUB rescue boot images.
|
||||
* Needed for ISOLINUX or GRUB boot images with platform ID 0.
|
||||
* The table is located at byte 8 of the boot image file.
|
||||
* Its size is 56 bytes.
|
||||
* The original boot image file on disk will not be modified.
|
||||
*
|
||||
* One may use el_torito_seems_boot_info_table() for a
|
||||
* qualified guess whether a boot info table is present in
|
||||
* the boot image. If the result is 1 then it should get bit0
|
||||
* set if its content gets copied to a new LBA.
|
||||
*
|
||||
* bit 1 -> 1 to generate a ISOLINUX isohybrid image with MBR.
|
||||
* ----------------------------------------------------------
|
||||
* @deprecated since 31 Mar 2010:
|
||||
@ -2695,6 +2701,17 @@ int el_torito_set_isolinux_options(ElToritoBootImage *bootimg,
|
||||
*/
|
||||
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag);
|
||||
|
||||
/** Deprecated:
|
||||
* Specifies that this image needs to be patched. This involves the writing
|
||||
* of a 16 bytes boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
*
|
||||
* @since 0.6.2
|
||||
* @deprecated Use el_torito_set_isolinux_options() instead
|
||||
*/
|
||||
void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
|
||||
|
||||
/**
|
||||
* Obtain a copy of the eventually loaded first 32768 bytes of the imported
|
||||
* session, the System Area.
|
||||
|
Loading…
Reference in New Issue
Block a user