Estimating size of El Torito boot images which are not represented by a file

This commit is contained in:
Thomas Schmitt 2014-04-27 12:09:13 +02:00
parent 25295d2bb0
commit 6d64bc23cf
5 changed files with 189 additions and 13 deletions

View File

@ -4416,7 +4416,7 @@ int iso_analyze_mips(IsoImage *image, IsoDataSource *src, int flag)
sai->mips_vd_entries[idx]->boot_bytes = iso_read_msb(upart + 12, 4);
ret = iso_tree_get_node_of_block(image, NULL,
sai->mips_vd_entries[idx]->boot_block / 4,
&node, 0);
&node, NULL, 0);
if (ret > 0)
sai->mips_boot_file_paths[idx] = iso_tree_get_node_path(node);
sai->num_mips_boot_files++;
@ -4455,7 +4455,7 @@ int iso_analyze_mipsel(IsoImage *image, IsoDataSource *src, int flag)
sai->mipsel_p_filesz = iso_read_lsb(usad + 24, 4) * 512;
sai->mipsel_seg_start = iso_read_lsb(usad + 28, 4);
ret = iso_tree_get_node_of_block(image, NULL, sai->mipsel_seg_start / 4,
&node, 0);
&node, NULL, 0);
if (ret > 0) {
sai->mipsel_boot_file_path = iso_tree_get_node_path(node);
file = (IsoFile *) node;
@ -4548,7 +4548,8 @@ int iso_analyze_sun(IsoImage *image, IsoDataSource *src, int flag)
last_core_block--;
if (last_core_block > 17 && last_core_block < sai->image_size) {
ret = iso_tree_get_node_of_block(image, NULL,
(uint32_t) last_core_block, &node, 0);
(uint32_t) last_core_block, &node,
NULL, 0);
if (ret > 0) {
iso_node_ref(node);
sai->sparc_core_node = (IsoFile *) node;
@ -4607,7 +4608,8 @@ int iso_analyze_hppa(IsoImage *image, IsoDataSource *src, int flag)
sai->hppa_bootloader_len = iso_read_msb(usad + 244, 4);
for (i = 0; i < 4; i++) {
paths[i] = NULL;
ret = iso_tree_get_node_of_block(image, NULL, adrs[i] / 2048, &node, 0);
ret = iso_tree_get_node_of_block(image, NULL, adrs[i] / 2048,
&node, NULL, 0);
if (ret > 0)
paths[i] = iso_tree_get_node_path(node);
}
@ -4684,18 +4686,101 @@ void iso_impsysa_report_text(struct iso_impsysa_result *target,
iso_impsysa_line(target, msg);
}
static
void iso_impsysa_reduce_na(uint32_t block, uint32_t *na, uint32_t claim)
{
if ((*na == 0 || *na > claim) && block < claim)
*na = claim;
}
static
int iso_impsysa_reduce_next_above(IsoImage *image, uint32_t block,
uint32_t *next_above, int flag)
{
int i;
struct iso_imported_sys_area *sai;
sai = image->imported_sa_info;
/* PVD, path table, root directory of active and of first session */
for (i = 0; i < sai->num_meta_struct_blocks; i++)
iso_impsysa_reduce_na(block, next_above, sai->meta_struct_blocks[i]);
/* Partition tables */
for (i = 0; i < sai->mbr_req_count; i++) {
iso_impsysa_reduce_na(block, next_above,
(uint32_t) (sai->mbr_req[i]->start_block / 4));
iso_impsysa_reduce_na(block, next_above,
(uint32_t) ((sai->mbr_req[i]->start_block +
sai->mbr_req[i]->block_count) / 4));
}
for (i = 0; i < sai->gpt_req_count; i++) {
iso_impsysa_reduce_na(block, next_above,
(uint32_t) (sai->gpt_req[i]->start_block / 4));
iso_impsysa_reduce_na(block, next_above,
(uint32_t) ((sai->gpt_req[i]->start_block +
sai->gpt_req[i]->block_count) / 4));
}
for (i = 0; i < sai->apm_req_count; i++) {
iso_impsysa_reduce_na(block, next_above,
(uint32_t) (sai->apm_req[i]->start_block /
(2048 / sai->apm_block_size)));
iso_impsysa_reduce_na(block, next_above,
(uint32_t) ((sai->apm_req[i]->start_block +
sai->apm_req[i]->block_count) /
(2048 / sai->apm_block_size)));
}
if (image->bootcat != NULL)
if (image->bootcat->node != NULL)
iso_impsysa_reduce_na(block, next_above, image->bootcat->node->lba);
iso_impsysa_reduce_na(block, next_above, sai->image_size);
return ISO_SUCCESS;
}
/* @param flag bit0= try to estimate the size if no path is found
*/
static
void iso_impsysa_report_blockpath(IsoImage *image,
struct iso_impsysa_result *target, char *msg,
uint32_t start_block, int flag)
{
int ret;
char *path;
char *path = NULL, *cpt;
IsoNode *node;
uint32_t next_above = 0;
uint32_t size;
ret = iso_tree_get_node_of_block(image, NULL, start_block, &node, 0);
if (ret <= 0)
ret = iso_tree_get_node_of_block(image, NULL, start_block,
&node, &next_above, 0);
if (ret <= 0) {
if (!(flag & 1))
return;
/* Look for next claimed block for estimating file size.
next_above already holds the best data file candidate.
*/
ret = iso_impsysa_reduce_next_above(image, start_block, &next_above, 0);
if (ret < 0)
return;
if (next_above == 0)
return;
size = next_above - start_block;
/* Replace in msg "path" by "blks", report number in bytes */
cpt = strstr(msg, "path");
if (cpt == NULL)
return;
path = iso_alloc_mem(strlen(msg) + 20, 1, 0);
if (path == NULL)
return;
strcpy(path, msg);
memcpy(path + (cpt - msg), "blks", 4);
sprintf(path + strlen(path), "%u", (unsigned int) size);
iso_impsysa_report_text(target, path, "", 0);
free(path);
return;
}
path = iso_tree_get_node_path(node);
if (path != NULL) {
iso_impsysa_report_text(target, msg, path, 0);
@ -5165,7 +5250,7 @@ int iso_eltorito_report(IsoImage *image, struct iso_impsysa_result *target,
continue;
img = bootcat->bootimages[i];
sprintf(msg, "El Torito img path : %3d ", i + 1);
iso_impsysa_report_blockpath(image, target, msg, lba_mem[i], 0);
iso_impsysa_report_blockpath(image, target, msg, lba_mem[i], 1);
}
ret = ISO_SUCCESS;
@ -5256,9 +5341,77 @@ int iso_image_report_system_area(IsoImage *image,
return iso_image_report_boot_eqp(image, 0, result, line_count, flag);
}
static
int iso_record_pvd_blocks(IsoImage *image, IsoDataSource *src, uint32_t block,
int flag)
{
int ret;
uint8_t *buffer = NULL;
struct iso_imported_sys_area *sai;
LIBISO_ALLOC_MEM(buffer, uint8_t, 2048);
sai = image->imported_sa_info;
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = block;
ret = src->read_block(src, block, buffer);
if (ret < 0)
goto ex;
/* Verify that it is a PVD of a volume not larger than sai->image_size */
if (buffer[0] != 1 || strncmp((char *) buffer + 1, "CD001", 5) != 0)
{ret = 0; goto ex;}
if (iso_read_lsb(buffer + 80, 4) > sai->image_size)
{ret = 0; goto ex;}
/* L pathtable, Opt L, M pathtable , Opt M, Root directory extent*/
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] =
iso_read_lsb(buffer + 140, 4);
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] =
iso_read_lsb(buffer + 144, 4);
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] =
iso_read_lsb(buffer + 148, 4);
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] =
iso_read_lsb(buffer + 152, 4);
sai->meta_struct_blocks[sai->num_meta_struct_blocks++] =
iso_read_lsb(buffer + 158, 4);
ret = ISO_SUCCESS;
ex:;
LIBISO_FREE_MEM(buffer);
return ret;
}
static
int iso_record_meta_struct_blocks(IsoImage *image, IsoDataSource *src,
int flag)
{
int ret;
struct iso_imported_sys_area *sai;
sai = image->imported_sa_info;
ret = iso_record_pvd_blocks(image, src, sai->pvd_block, 0);
if (ret < 0)
goto ex;
/* Try block 32 as first session PVD */
ret = iso_record_pvd_blocks(image, src, 16, 0);
if (ret < 0)
goto ex;
if (ret == 0 && sai->pvd_block > 16) {
/* No emulated multi-session: Try block 16 as first session PVD */
ret = iso_record_pvd_blocks(image, src, 16, 0);
if (ret < 0)
goto ex;
}
ret = ISO_SUCCESS;
ex:
return ret;
}
static
int iso_analyze_system_area(IsoImage *image, IsoDataSource *src,
uint32_t image_size, int flag)
struct iso_read_opts *opts, uint32_t image_size,
int flag)
{
int ret, i, sao, sa_type, sa_sub, is_mbr = 0;
@ -5274,6 +5427,7 @@ int iso_analyze_system_area(IsoImage *image, IsoDataSource *src,
image->imported_sa_info->is_not_zero = 1;
image->imported_sa_info->image_size = image_size;
image->imported_sa_info->pvd_block = opts->block + 16;
ret = iso_analyze_mbr(image, src, 0);
if (ret < 0)
@ -5309,6 +5463,9 @@ int iso_analyze_system_area(IsoImage *image, IsoDataSource *src,
if (ret < 0)
goto ex;
}
ret = iso_record_meta_struct_blocks(image, src, 0);
if (ret < 0)
goto ex;
ret = ISO_SUCCESS;
ex:;
@ -5646,7 +5803,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
goto import_revert;
if (opts->load_system_area && image->system_area_data != NULL) {
ret = iso_analyze_system_area(image, src, data->nblocks, 0);
ret = iso_analyze_system_area(image, src, opts, data->nblocks, 0);
if (ret < 0) {
iso_msg_submit(-1, ISO_SYSAREA_PROBLEMS, 0,
"Problem encountered during inspection of System Area:");

View File

@ -280,6 +280,9 @@ struct iso_imported_sys_area {
/* Giving the error number if the assessment ended by an error */
int overall_return;
/* Block address of loaded Primar Volume Descriptor */
uint32_t pvd_block;
/* Size of the imported ISO image */
uint32_t image_size;
@ -380,6 +383,11 @@ struct iso_imported_sys_area {
char *hppa_ramdisk;
char *hppa_bootloader;
/* Some block addresses of active and first session:
PVD, L Pathtable, Opt L, M Pathtable, Opt M, root directory
*/
uint32_t meta_struct_blocks[12];
int num_meta_struct_blocks;
};
int iso_imported_sa_new(struct iso_imported_sys_area **sa_info, int flag);

View File

@ -3974,6 +3974,9 @@ int iso_image_report_system_area(IsoImage *image,
" tells the path to the data file in the ISO image which belongs to", \
" the block address given by LBA of boot image X.", \
" (This line is not reported if no path points to that block.)", \
" El Torito img blks : X decimal", \
" gives an upper limit of the number of blocks in the boot image", \
" if it is not accessible via a path in the ISO directory tree.", \
""
/**

View File

@ -1191,7 +1191,7 @@ ex:;
@param flag bit0= recursion
*/
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
IsoNode **found, int flag)
IsoNode **found, uint32_t *next_above, int flag)
{
int ret, section_count, i;
IsoDirIter *iter = NULL;
@ -1199,6 +1199,7 @@ int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
IsoDir *subdir;
IsoFile *file;
struct iso_file_section *sections = NULL;
uint32_t na = 0;
if (dir == NULL)
dir = image->root;
@ -1219,15 +1220,22 @@ int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
*found = node;
ret = 1; goto ex;
}
if ((na == 0 || sections[i].block < na) &&
sections[i].block > block)
na = sections[i].block;
}
free(sections); sections = NULL;
} else if (ISO_NODE_IS_DIR(node)) {
subdir = (IsoDir *) node;
ret = iso_tree_get_node_of_block(image, subdir, block, found, 1);
ret = iso_tree_get_node_of_block(image, subdir, block, found, &na,
1);
if (ret != 0)
goto ex;
}
}
if (next_above != NULL && (na > 0 || !(flag & 1)))
if (*next_above == 0 || *next_above > na || !(flag & 1))
*next_above = na;
ret = 0;
ex:
if (sections != NULL)

View File

@ -21,7 +21,7 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir);
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
IsoNode **found, int flag);
IsoNode **found, uint32_t *next_above, int flag);
#endif /*LIBISO_IMAGE_TREE_H_*/