Added support for multiple boot images.

New API calls iso_image_add_boot_image() , iso_image_get_all_boot_imgs(),
el_torito_get_boot_platform_id(), el_torito_get_load_seg(),
el_torito_get_load_size(), el_torito_get_bootable()
This commit is contained in:
Thomas Schmitt 2010-04-22 14:04:51 +02:00
parent da2c0520cc
commit 59d143c1f0
8 changed files with 431 additions and 108 deletions

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2010 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
@ -72,7 +72,8 @@ void ecma119_image_free(Ecma119Image *t)
free(t->input_charset); free(t->input_charset);
if (t->output_charset != NULL) if (t->output_charset != NULL)
free(t->output_charset); free(t->output_charset);
if (t->bootsrc != NULL)
free(t->bootsrc);
if (t->system_area_data != NULL) if (t->system_area_data != NULL)
free(t->system_area_data); free(t->system_area_data);
@ -1166,6 +1167,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
/* el-torito? */ /* el-torito? */
target->eltorito = (src->bootcat == NULL ? 0 : 1); target->eltorito = (src->bootcat == NULL ? 0 : 1);
target->catalog = src->bootcat; target->catalog = src->bootcat;
target->num_bootsrc = target->catalog->num_bootimages;
target->bootsrc = calloc(target->num_bootsrc + 1,
sizeof(IsoFileSrc *));
if (target->bootsrc == NULL) {
ret = ISO_OUT_OF_MEM;
goto target_cleanup;
}
for (i= 0; i < target->num_bootsrc; i++)
target->bootsrc[i] = NULL;
if (opts->system_area_data != NULL) { if (opts->system_area_data != NULL) {
system_area = opts->system_area_data; system_area = opts->system_area_data;

View File

@ -454,7 +454,10 @@ struct ecma119_image
*/ */
struct el_torito_boot_catalog *catalog; struct el_torito_boot_catalog *catalog;
IsoFileSrc *cat; /**< location of the boot catalog in the new image */ IsoFileSrc *cat; /**< location of the boot catalog in the new image */
IsoFileSrc *bootimg; /**< location of the boot image in the new image */
/* ts B00420 */
int num_bootsrc;
IsoFileSrc **bootsrc; /* location of the boot images in the new image */
/* /*
* System Area related information * System Area related information

View File

@ -18,6 +18,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
/** /**
* This table should be written with the actual values at offset * This table should be written with the actual values at offset
@ -63,6 +64,12 @@ int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id)
return 1; return 1;
} }
/* API */
int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg)
{
return bootimg->platform_id;
}
/** /**
* Sets the load segment for the initial boot image. This is only for * Sets the load segment for the initial boot image. This is only for
* no emulation boot images, and is a NOP for other image types. * no emulation boot images, and is a NOP for other image types.
@ -74,6 +81,14 @@ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment)
bootimg->load_seg = segment; bootimg->load_seg = segment;
} }
/* API */
int el_torito_get_load_seg(ElToritoBootImage *bootimg)
{
if (bootimg->load_seg < 0)
return 0xffff - bootimg->load_seg;
return bootimg->load_seg;
}
/** /**
* Sets the number of sectors (512b) to be load at load segment during * Sets the number of sectors (512b) to be load at load segment during
* the initial boot procedure. This is only for no emulation boot images, * the initial boot procedure. This is only for no emulation boot images,
@ -86,6 +101,14 @@ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors)
bootimg->load_size = sectors; bootimg->load_size = sectors;
} }
/* API */
int el_torito_get_load_size(ElToritoBootImage *bootimg)
{
if (bootimg->load_size < 0)
return 0xffff - bootimg->load_size;
return bootimg->load_size;
}
/** /**
* Marks the specified boot image as not bootable * Marks the specified boot image as not bootable
*/ */
@ -94,6 +117,12 @@ void el_torito_set_no_bootable(ElToritoBootImage *bootimg)
bootimg->bootable = 0; bootimg->bootable = 0;
} }
/* API */
int el_torito_get_bootable(ElToritoBootImage *bootimg)
{
return !!bootimg->bootable;
}
/** /**
* Specifies that this image needs to be patched. This involves the writting * Specifies that this image needs to be patched. This involves the writting
* of a 56 bytes boot information table at offset 8 of the boot image file. * of a 56 bytes boot information table at offset 8 of the boot image file.
@ -360,7 +389,7 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
const char *catalog_path, const char *catalog_path,
ElToritoBootImage **boot) ElToritoBootImage **boot)
{ {
int ret; int ret, i;
struct el_torito_boot_catalog *catalog; struct el_torito_boot_catalog *catalog;
ElToritoBootImage *boot_image= NULL; ElToritoBootImage *boot_image= NULL;
IsoBoot *cat_node= NULL; IsoBoot *cat_node= NULL;
@ -424,7 +453,10 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
goto boot_image_cleanup; goto boot_image_cleanup;
} }
catalog->image = boot_image; catalog->num_bootimages = 1;
catalog->bootimages[0] = boot_image;
for (i = 1; i < Libisofs_max_boot_imageS; i++)
catalog->bootimages[i] = NULL;
catalog->node = cat_node; catalog->node = cat_node;
catalog->sort_weight = 1000; /* slightly high */ catalog->sort_weight = 1000; /* slightly high */
iso_node_ref((IsoNode*)cat_node); iso_node_ref((IsoNode*)cat_node);
@ -449,7 +481,7 @@ boot_image_cleanup:;
} }
/** /**
* Get El-Torito boot image of an ISO image, if any. * Get the boot catalog and the El-Torito default boot image of an ISO image.
* *
* This can be useful, for example, to check if a volume read from a previous * This can be useful, for example, to check if a volume read from a previous
* session or an existing image is bootable. It can also be useful to get * session or an existing image is bootable. It can also be useful to get
@ -493,10 +525,10 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
/* ok, image is bootable */ /* ok, image is bootable */
if (boot) { if (boot) {
*boot = image->bootcat->image; *boot = image->bootcat->bootimages[0];
} }
if (imgnode) { if (imgnode) {
*imgnode = image->bootcat->image->image; *imgnode = image->bootcat->bootimages[0]->image;
} }
if (catnode) { if (catnode) {
*catnode = image->bootcat->node; *catnode = image->bootcat->node;
@ -504,6 +536,40 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
return ISO_SUCCESS; return ISO_SUCCESS;
} }
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
{
int i;
struct el_torito_boot_catalog *cat;
if (image == NULL)
return ISO_NULL_POINTER;
if (image->bootcat == NULL)
return 0;
cat = image->bootcat;
*num_boots = cat->num_bootimages;
*boots = NULL;
*bootnodes = NULL;
if (*num_boots <= 0)
return 0;
*boots = calloc(*num_boots, sizeof(ElToritoBootImage *));
*bootnodes = calloc(*num_boots, sizeof(IsoFile *));
if(*boots == NULL || *bootnodes == NULL) {
if (*boots != NULL)
free(*boots);
if (*bootnodes != NULL)
free(*bootnodes);
*boots = NULL;
*bootnodes = NULL;
return ISO_OUT_OF_MEM;
}
for (i = 0; i < *num_boots; i++) {
(*boots)[i] = cat->bootimages[i];
(*bootnodes)[i] = image->bootcat->bootimages[i]->image;
}
return 1;
}
/** /**
* Removes the El-Torito bootable image. * Removes the El-Torito bootable image.
* *
@ -528,6 +594,28 @@ void iso_image_remove_boot_image(IsoImage *image)
image->bootcat = NULL; image->bootcat = NULL;
} }
/* ts B00420 */
/* future API */
int iso_image_add_boot_image(IsoImage *image, const char *image_path,
enum eltorito_boot_media_type type, int flag,
ElToritoBootImage **boot)
{
int ret;
struct el_torito_boot_catalog *catalog = image->bootcat;
ElToritoBootImage *boot_img;
if (catalog->num_bootimages >= Libisofs_max_boot_imageS)
return ISO_BOOT_IMAGE_OVERFLOW;
ret = create_image(image, image_path, type, &boot_img);
if (ret < 0)
return ret;
catalog->bootimages[catalog->num_bootimages] = boot_img;
catalog->num_bootimages++;
if (boot != NULL)
*boot = boot_img;
return 1;
}
/* API */ /* API */
int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight) int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight)
{ {
@ -540,14 +628,19 @@ int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight)
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat) void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
{ {
struct el_torito_boot_image *image; struct el_torito_boot_image *image;
int i;
if (cat == NULL) { if (cat == NULL) {
return; return;
} }
image = cat->image; for (i = 0; i < Libisofs_max_boot_imageS; i++) {
iso_node_unref((IsoNode*)image->image); image = cat->bootimages[i];
free(image); if (image == NULL)
continue;
iso_node_unref((IsoNode*)image->image);
free(image);
}
iso_node_unref((IsoNode*)cat->node); iso_node_unref((IsoNode*)cat->node);
free(cat); free(cat);
} }
@ -560,11 +653,6 @@ struct catalog_stream
Ecma119Image *target; Ecma119Image *target;
uint8_t buffer[BLOCK_SIZE]; uint8_t buffer[BLOCK_SIZE];
int offset; /* -1 if stream is not opened */ int offset; /* -1 if stream is not opened */
/* ts B00419 */
/* Byte 1 of Validation Entry: 0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */
uint8_t platform_id;
}; };
static void static void
@ -576,7 +664,6 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id)
struct el_torito_validation_entry *ve = struct el_torito_validation_entry *ve =
(struct el_torito_validation_entry*)buf; (struct el_torito_validation_entry*)buf;
ve->header_id[0] = 1; ve->header_id[0] = 1;
/* 0: 80x86, 1: PowerPC, 2: Mac, 0xef: EFI */
ve->platform_id[0] = platform_id; ve->platform_id[0] = platform_id;
ve->key_byte1[0] = 0x55; ve->key_byte1[0] = 0x55;
ve->key_byte2[0] = 0xAA; ve->key_byte2[0] = 0xAA;
@ -589,31 +676,58 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id)
iso_lsb(ve->checksum, checksum, 2); iso_lsb(ve->checksum, checksum, 2);
} }
static void
write_section_header(uint8_t *buf, Ecma119Image *t, int idx) {
int pi;
char *id_string;
struct el_torito_section_header *e =
(struct el_torito_section_header *) buf;
/* 0x90 = more section headers follow , 0x91 = final section */
e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - 1);
pi= e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
e->num_entries[0] = 1;
e->num_entries[1] = 0;
id_string = (char *) e->id_string;
memset(id_string, 0, sizeof(e->id_string));
/* >>> ???
El-Torito 1.0 , chapter 2.3 :
"If the BIOS understands the ID, string it may choose to boot
the system using one of these entries ..."
*/
}
/** /**
* Write one section entry. * Write one section entry.
* Currently this is used only for default image (the only supported just now) * Usable for the Default Entry
* and for Section Entries with Selection criteria type == 0
*/ */
static void static void
write_section_entry(uint8_t *buf, Ecma119Image *t) write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
{ {
struct el_torito_boot_image *img; struct el_torito_boot_image *img;
struct el_torito_section_entry *se = struct el_torito_section_entry *se =
(struct el_torito_section_entry*)buf; (struct el_torito_section_entry*)buf;
img = t->catalog->image; img = t->catalog->bootimages[idx];
se->boot_indicator[0] = img->bootable ? 0x88 : 0x00; se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
se->boot_media_type[0] = img->type; se->boot_media_type[0] = img->type;
iso_lsb(se->load_seg, img->load_seg, 2); iso_lsb(se->load_seg, img->load_seg, 2);
se->system_type[0] = img->partition_type; se->system_type[0] = img->partition_type;
iso_lsb(se->sec_count, img->load_size, 2); iso_lsb(se->sec_count, img->load_size, 2);
iso_lsb(se->block, t->bootimg->sections[0].block, 4); iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4);
} }
static static
int catalog_open(IsoStream *stream) int catalog_open(IsoStream *stream)
{ {
int i;
struct catalog_stream *data; struct catalog_stream *data;
if (stream == NULL) { if (stream == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
@ -626,11 +740,18 @@ int catalog_open(IsoStream *stream)
memset(data->buffer, 0, BLOCK_SIZE); memset(data->buffer, 0, BLOCK_SIZE);
/* fill the buffer with the catalog contents */ /* fill the buffer with the catalog contents */
write_validation_entry(data->buffer, data->platform_id); write_validation_entry(data->buffer,
data->target->catalog->bootimages[0]->platform_id);
/* write default entry */ /* write default entry = first boot image */
write_section_entry(data->buffer + 32, data->target); write_section_entry(data->buffer + 32, data->target, 0);
/* ts B00420 */
/* (The maximum number of boot images must fit into BLOCK_SIZE) */
for (i = 1; i < data->target->catalog->num_bootimages; i++) {
write_section_header(data->buffer + i * 64, data->target, i);
write_section_entry(data->buffer + i * 64 + 32, data->target, i);
}
data->offset = 0; data->offset = 0;
return ISO_SUCCESS; return ISO_SUCCESS;
} }
@ -743,7 +864,6 @@ int catalog_stream_new(Ecma119Image *target, IsoStream **stream)
/* fill data */ /* fill data */
data->target = target; data->target = target;
data->offset = -1; data->offset = -1;
data->platform_id = target->catalog->image->platform_id;
str->refcount = 1; str->refcount = 1;
str->data = data; str->data = data;
@ -807,7 +927,7 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
* 1 on success, 0 error (but continue), < 0 error * 1 on success, 0 error (but continue), < 0 error
*/ */
static static
int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize) int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
{ {
struct boot_info_table *info; struct boot_info_table *info;
uint32_t checksum; uint32_t checksum;
@ -840,7 +960,7 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize)
info = (struct boot_info_table*)(buf + 8); info = (struct boot_info_table*)(buf + 8);
/*memset(info, 0, sizeof(struct boot_info_table));*/ /*memset(info, 0, sizeof(struct boot_info_table));*/
iso_lsb(info->bi_pvd, t->ms_block + 16, 4); iso_lsb(info->bi_pvd, t->ms_block + 16, 4);
iso_lsb(info->bi_file, t->bootimg->sections[0].block, 4); iso_lsb(info->bi_file, t->bootsrc[idx]->sections[0].block, 4);
iso_lsb(info->bi_length, imgsize, 4); iso_lsb(info->bi_length, imgsize, 4);
iso_lsb(info->bi_csum, checksum, 4); iso_lsb(info->bi_csum, checksum, 4);
return ISO_SUCCESS; return ISO_SUCCESS;
@ -854,7 +974,11 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
* this is a good place to do so. * this is a good place to do so.
*/ */
Ecma119Image *t; Ecma119Image *t;
int ret; int ret, idx;
size_t size;
uint8_t *buf;
IsoStream *new = NULL;
IsoStream *original = NULL;
if (writer == NULL) { if (writer == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
@ -862,12 +986,12 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
t = writer->target; t = writer->target;
if (t->catalog->image->isolinux_options & 0x01) { /* ts B00420 : now in loop */
/* we need to patch the image */ /* Patch the boot image info tables if indicated */
size_t size; for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
uint8_t *buf; if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
IsoStream *new = NULL; continue;
IsoStream *original = t->bootimg->stream; original = t->bootsrc[idx]->stream;
size = (size_t) iso_stream_get_size(original); size = (size_t) iso_stream_get_size(original);
buf = calloc(1, size); buf = calloc(1, size);
if (buf == NULL) { if (buf == NULL) {
@ -884,7 +1008,7 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
} }
/* ok, patch the read buffer */ /* ok, patch the read buffer */
ret = patch_boot_image(buf, t, size); ret = patch_boot_image(buf, t, size, idx);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -895,7 +1019,7 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
t->bootimg->stream = new; t->bootsrc[idx]->stream = new;
iso_stream_unref(original); iso_stream_unref(original);
} }
return ISO_SUCCESS; return ISO_SUCCESS;
@ -946,7 +1070,7 @@ int eltorito_writer_free_data(IsoImageWriter *writer)
int eltorito_writer_create(Ecma119Image *target) int eltorito_writer_create(Ecma119Image *target)
{ {
int ret; int ret, idx;
IsoImageWriter *writer; IsoImageWriter *writer;
IsoFile *bootimg; IsoFile *bootimg;
IsoFileSrc *src; IsoFileSrc *src;
@ -977,16 +1101,20 @@ int eltorito_writer_create(Ecma119Image *target)
return ret; return ret;
} }
} }
bootimg = target->catalog->image->image;
ret = iso_file_src_create(target, bootimg, &src);
if (ret < 0) {
return ret;
}
target->bootimg = src;
/* if we have selected to patch the image, it needs to be copied always */ /* ts B00420 : now in a loop */
if (target->catalog->image->isolinux_options & 0x01) { for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
src->prev_img = 0; bootimg = target->catalog->bootimages[idx]->image;
ret = iso_file_src_create(target, bootimg, &src);
if (ret < 0) {
return ret;
}
target->bootsrc[idx] = src;
/* For patching an image, it needs to be copied always */
if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
src->prev_img = 0;
}
} }
/* we need the bootable volume descriptor */ /* we need the bootable volume descriptor */

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2010 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
@ -27,16 +28,20 @@ struct Iso_Boot
IsoNode node; IsoNode node;
}; };
/* Not more than 32 so that all entries fit into 2048 bytes */
#define Libisofs_max_boot_imageS 32
struct el_torito_boot_catalog { struct el_torito_boot_catalog {
IsoBoot *node; /* node of the catalog */ IsoBoot *node; /* node of the catalog */
struct el_torito_boot_image *image; /* default boot image */
/* ts B00419 */
int num_bootimages;
struct el_torito_boot_image *bootimages[Libisofs_max_boot_imageS];
/* [0]= default boot image */
/* ts B00419 */ /* ts B00419 */
/* Weight value for image sorting */ /* Weight value for image sorting */
int sort_weight; int sort_weight;
/* >>> ts B00419 : List of further boot images */
}; };
struct el_torito_boot_image { struct el_torito_boot_image {
@ -88,8 +93,8 @@ struct el_torito_default_entry {
struct el_torito_section_header { struct el_torito_section_header {
uint8_t header_indicator BP(1, 1); uint8_t header_indicator BP(1, 1);
uint8_t platform_id BP(2, 2); uint8_t platform_id BP(2, 2);
uint8_t number BP(3, 4); uint8_t num_entries BP(3, 4);
uint8_t character BP(5, 32); uint8_t id_string BP(5, 32);
}; };
/** El-Torito, 2.4 */ /** El-Torito, 2.4 */

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2010 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
@ -279,12 +279,19 @@ typedef struct
/* el-torito information */ /* el-torito information */
unsigned int eltorito : 1; /* is el-torito available */ unsigned int eltorito : 1; /* is el-torito available */
unsigned int bootable:1; /**< If the entry is bootable. */ /* ts B00419 */
unsigned char type; /**< The type of image */ int num_bootimgs;
unsigned char partition_type; /**< type of partition for HD-emul images */ unsigned char platform_ids[Libisofs_max_boot_imageS];
short load_seg; /**< Load segment for the initial boot image. */ unsigned char boot_flags[Libisofs_max_boot_imageS]; /* bit0= bootable */
short load_size; /**< Number of sectors to load. */ unsigned char media_types[Libisofs_max_boot_imageS];
uint32_t imgblock; /**< Block for El-Torito boot image */ unsigned char partition_types[Libisofs_max_boot_imageS];
short load_segs[Libisofs_max_boot_imageS];
short load_sizes[Libisofs_max_boot_imageS];
/** Block addresses of for El-Torito boot images.
Needed to recognize them when the get read from the directory tree.
*/
uint32_t bootblocks[Libisofs_max_boot_imageS];
uint32_t catblock; /**< Block for El-Torito catalog */ uint32_t catblock; /**< Block for El-Torito catalog */
/* Whether inode numbers from PX entries shall be discarded */ /* Whether inode numbers from PX entries shall be discarded */
@ -2191,9 +2198,10 @@ int read_pvm(_ImageFsData *data, uint32_t block)
static static
int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
{ {
int ret; int ret, i, rx, last_done, idx;
struct el_torito_validation_entry *ve; struct el_torito_validation_entry *ve;
struct el_torito_default_entry *entry; struct el_torito_section_header *sh;
struct el_torito_section_entry *entry; /* also usable as default_entry */
unsigned char buffer[BLOCK_SIZE]; unsigned char buffer[BLOCK_SIZE];
ret = data->src->read_block(data->src, block, buffer); ret = data->src->read_block(data->src, block, buffer);
@ -2223,17 +2231,47 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
/* ok, once we are here we assume it is a valid catalog */ /* ok, once we are here we assume it is a valid catalog */
/* parse the default entry */ /* parse the default entry */
entry = (struct el_torito_default_entry *)(buffer + 32); entry = (struct el_torito_section_entry *)(buffer + 32);
data->eltorito = 1; data->eltorito = 1;
data->bootable = entry->boot_indicator[0] ? 1 : 0; /* ts B00420 */
data->type = entry->boot_media_type[0]; /* The Default Entry is declared mandatory */
data->partition_type = entry->system_type[0]; data->num_bootimgs = 1;
data->load_seg = iso_read_lsb(entry->load_seg, 2); data->platform_ids[0] = ve->platform_id[0];
data->load_size = iso_read_lsb(entry->sec_count, 2); data->boot_flags[0] = entry->boot_indicator[0] ? 1 : 0;
data->imgblock = iso_read_lsb(entry->block, 4); data->media_types[0] = entry->boot_media_type[0];
data->partition_types[0] = entry->system_type[0];
data->load_segs[0] = iso_read_lsb(entry->load_seg, 2);
data->load_sizes[0] = iso_read_lsb(entry->sec_count, 2);
data->bootblocks[0] = iso_read_lsb(entry->block, 4);
/* TODO #00018 : check if there are more entries in the boot catalog */ /* ts B00420 : Read eventual more entries from the boot catalog */
last_done = 0;
for (rx = 64; (buffer[rx] & 0xfe) == 0x90 && !last_done; rx += 32) {
last_done = buffer[rx] & 1;
/* Read Section Header */
sh = (struct el_torito_section_header *) (buffer + rx);
for (i = 0; i < sh->num_entries[0]; i++) {
rx += 32;
if (data->num_bootimgs >= Libisofs_max_boot_imageS) {
ret = iso_msg_submit(data->msgid, ISO_EL_TORITO_WARN, 0,
"Too many boot images found. List truncated.");
goto after_bootblocks;
}
/* Read bootblock from section entry */
entry = (struct el_torito_section_entry *)(buffer + rx);
idx = data->num_bootimgs;
data->platform_ids[idx] = sh->platform_id[0];
data->boot_flags[idx] = entry->boot_indicator[0] ? 1 : 0;
data->media_types[idx] = entry->boot_media_type[0];
data->partition_types[idx] = entry->system_type[0];
data->load_segs[idx] = iso_read_lsb(entry->load_seg, 2);
data->load_sizes[idx] = iso_read_lsb(entry->sec_count, 2);
data->bootblocks[idx] = iso_read_lsb(entry->block, 4);
data->num_bootimgs++;
}
}
after_bootblocks:;
return ISO_SUCCESS; return ISO_SUCCESS;
} }
@ -2318,7 +2356,7 @@ ex:
int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
int msgid, IsoImageFilesystem **fs) int msgid, IsoImageFilesystem **fs)
{ {
int ret; int ret, i;
uint32_t block; uint32_t block;
IsoImageFilesystem *ifs; IsoImageFilesystem *ifs;
_ImageFsData *data; _ImageFsData *data;
@ -2357,9 +2395,13 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
data->md5_load = !opts->nomd5; data->md5_load = !opts->nomd5;
data->aaip_version = -1; data->aaip_version = -1;
data->make_new_ino = opts->make_new_ino; data->make_new_ino = opts->make_new_ino;
data->num_bootimgs = 0;
for (i = 0; i < Libisofs_max_boot_imageS; i++)
data->bootblocks[i] = 0;
data->inode_counter = 0; data->inode_counter = 0;
data->px_ino_status = 0; data->px_ino_status = 0;
data->local_charset = strdup(iso_get_local_charset(0)); data->local_charset = strdup(iso_get_local_charset(0));
if (data->local_charset == NULL) { if (data->local_charset == NULL) {
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
@ -2608,7 +2650,7 @@ static
int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image, int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
IsoFileSource *src, IsoNode **node) IsoFileSource *src, IsoNode **node)
{ {
int ret; int ret, idx;
struct stat info; struct stat info;
IsoNode *new; IsoNode *new;
char *name; char *name;
@ -2720,11 +2762,17 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
new = (IsoNode*) file; new = (IsoNode*) file;
new->refcount = 0; new->refcount = 0;
if (fsdata->eltorito && data->sections[0].block == fsdata->imgblock) { /* ts B00419 */
for (idx = 0; idx < fsdata->num_bootimgs; idx++)
if (fsdata->eltorito && data->sections[0].block ==
fsdata->bootblocks[idx])
break;
if (idx < fsdata->num_bootimgs) {
/* it is boot image node */ /* it is boot image node */
if (image->bootcat->image->image != NULL) {
if (image->bootcat->bootimages[idx]->image != NULL) {
ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0, ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
"More than one image node has been found."); "More than one ISO node has been found for the same boot image.");
if (ret < 0) { if (ret < 0) {
free(name); free(name);
iso_stream_unref(stream); iso_stream_unref(stream);
@ -2732,7 +2780,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
} }
} else { } else {
/* and set the image node */ /* and set the image node */
image->bootcat->image->image = file; image->bootcat->bootimages[idx]->image = file;
new->refcount++; new->refcount++;
} }
} }
@ -2872,7 +2920,7 @@ int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder)
* accessible from the ISO filesystem. * accessible from the ISO filesystem.
*/ */
static static
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image, int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image, int idx,
IsoFileSource **src) IsoFileSource **src)
{ {
int ret; int ret;
@ -2930,7 +2978,8 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image,
ifsdata->info = atts; ifsdata->info = atts;
ifsdata->name = NULL; ifsdata->name = NULL;
ifsdata->sections[0].block = fsdata->imgblock; /* ts B00420 */
ifsdata->sections[0].block = fsdata->bootblocks[idx];
ifsdata->sections[0].size = BLOCK_SIZE; ifsdata->sections[0].size = BLOCK_SIZE;
ifsdata->nsections = 1; ifsdata->nsections = 1;
@ -2952,7 +3001,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
struct iso_read_opts *opts, struct iso_read_opts *opts,
IsoReadImageFeatures **features) IsoReadImageFeatures **features)
{ {
int ret, hflag, i; int ret, hflag, i, idx;
IsoImageFilesystem *fs; IsoImageFilesystem *fs;
IsoFilesystem *fsback; IsoFilesystem *fsback;
IsoNodeBuilder *blback; IsoNodeBuilder *blback;
@ -2961,6 +3010,8 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
_ImageFsData *data; _ImageFsData *data;
struct el_torito_boot_catalog *oldbootcat; struct el_torito_boot_catalog *oldbootcat;
uint8_t *rpt; uint8_t *rpt;
IsoFileSource *boot_src;
IsoNode *node;
#ifdef Libisofs_with_checksumS #ifdef Libisofs_with_checksumS
uint32_t old_checksum_start_lba; uint32_t old_checksum_start_lba;
@ -3066,23 +3117,32 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
struct el_torito_boot_catalog *catalog; struct el_torito_boot_catalog *catalog;
ElToritoBootImage *boot_image= NULL; ElToritoBootImage *boot_image= NULL;
boot_image = calloc(1, sizeof(ElToritoBootImage));
if (boot_image == NULL) {
ret = ISO_OUT_OF_MEM;
goto import_revert;
}
boot_image->bootable = data->bootable;
boot_image->type = data->type;
boot_image->partition_type = data->partition_type;
boot_image->load_seg = data->load_seg;
boot_image->load_size = data->load_size;
catalog = calloc(1, sizeof(struct el_torito_boot_catalog)); catalog = calloc(1, sizeof(struct el_torito_boot_catalog));
if (catalog == NULL) { if (catalog == NULL) {
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
goto import_revert; goto import_revert;
} }
catalog->image = boot_image;
/* ts B00421 */
catalog->num_bootimages = 0;
for (idx = 0; idx < data->num_bootimgs; idx++) {
boot_image = calloc(1, sizeof(ElToritoBootImage));
if (boot_image == NULL) {
ret = ISO_OUT_OF_MEM;
goto import_revert;
}
boot_image->bootable = data->boot_flags[idx] & 1;
boot_image->type = data->media_types[idx];
boot_image->partition_type = data->partition_types[idx];
boot_image->load_seg = data->load_segs[idx];
boot_image->load_size = data->load_sizes[idx];
boot_image->platform_id = data->platform_ids[idx];
catalog->bootimages[catalog->num_bootimages] = boot_image;
catalog->num_bootimages++;
}
for ( ; idx < Libisofs_max_boot_imageS; idx++)
catalog->bootimages[idx] = NULL;
image->bootcat = catalog; image->bootcat = catalog;
} }
@ -3116,21 +3176,25 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
} }
if (data->eltorito) { if (data->eltorito) {
/* if catalog and image nodes were not filled, we create them here */ /* if catalog and boot image nodes were not filled,
if (image->bootcat->image->image == NULL) { we create them here */
IsoFileSource *src;
IsoNode *node; /* ts B00419 : now in a loop */
ret = create_boot_img_filesrc(fs, image, &src); for (idx = 0; idx < image->bootcat->num_bootimages; idx++) {
if (image->bootcat->bootimages[idx]->image != NULL)
continue;
ret = create_boot_img_filesrc(fs, image, idx, &boot_src);
if (ret < 0) { if (ret < 0) {
iso_node_builder_unref(image->builder); iso_node_builder_unref(image->builder);
goto import_revert; goto import_revert;
} }
ret = image_builder_create_node(image->builder, image, src, &node); ret = image_builder_create_node(image->builder, image, boot_src,
&node);
if (ret < 0) { if (ret < 0) {
iso_node_builder_unref(image->builder); iso_node_builder_unref(image->builder);
goto import_revert; goto import_revert;
} }
image->bootcat->image->image = (IsoFile*)node; image->bootcat->bootimages[idx]->image = (IsoFile*)node;
/* warn about hidden images */ /* warn about hidden images */
iso_msg_submit(image->id, ISO_EL_TORITO_HIDDEN, 0, iso_msg_submit(image->id, ISO_EL_TORITO_HIDDEN, 0,

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009-2010 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
@ -2283,16 +2283,15 @@ void iso_image_set_biblio_file_id(IsoImage *image, const char *biblio_file_id);
const char *iso_image_get_biblio_file_id(const IsoImage *image); const char *iso_image_get_biblio_file_id(const IsoImage *image);
/** /**
* Create a bootable image by adding a El-Torito boot image. * Create a new set of El-Torito bootable images by adding a boot catalog
* * and the default boot image.
* This also add a catalog boot node to the image filesystem tree. * Further boot images may then be added by iso_image_add_boot_image().
* *
* @param image * @param image
* The image to make bootable. If it was already bootable this function * The image to make bootable. If it was already bootable this function
* returns an error and the image remains unmodified. * returns an error and the image remains unmodified.
* @param image_path * @param image_path
* The absolute path on the image tree of a regular file to use as * The absolute path of a IsoFile to be used as default boot image.
* default boot image.
* @param type * @param type
* The boot media type. This can be one of 3 types: * The boot media type. This can be one of 3 types:
* - Floppy emulation: Boot image file must be exactly * - Floppy emulation: Boot image file must be exactly
@ -2325,10 +2324,36 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
const char *catalog_path, const char *catalog_path,
ElToritoBootImage **boot); ElToritoBootImage **boot);
/**
* Add a further boot image to the set of El-Torito bootable images.
* This set has already to be created by iso_image_set_boot_image().
* Up to 31 further boot images may be added.
*
* @param image
* The image to which the boot image shall be added.
* returns an error and the image remains unmodified.
* @param image_path
* The absolute path of a IsoFile to be used as default boot image.
* @param type
* The boot media type. See iso_image_set_boot_image
* @param flag
* Bitfield for control purposes. Unused yet. Submit 0.
* @param boot
* Location where a pointer to the added boot image will be stored.
* See iso_image_set_boot_image
* @return
* 1 on success, < 0 on error
*
* @since 0.6.32
*/
int iso_image_add_boot_image(IsoImage *image, const char *image_path,
enum eltorito_boot_media_type type, int flag,
ElToritoBootImage **boot);
/* TODO #00026 : add support for "hidden" bootable images. */ /* TODO #00026 : add support for "hidden" bootable images. */
/** /**
* Get El-Torito boot image of an ISO image, if any. * Get the El-Torito boot catalog and the default boot image of an ISO image.
* *
* This can be useful, for example, to check if a volume read from a previous * This can be useful, for example, to check if a volume read from a previous
* session or an existing image is bootable. It can also be useful to get * session or an existing image is bootable. It can also be useful to get
@ -2365,6 +2390,34 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
IsoFile **imgnode, IsoBoot **catnode); IsoFile **imgnode, IsoBoot **catnode);
/**
* Get all El-Torito boot images of an ISO image.
*
* The first of these boot images is the same as returned by
* iso_image_get_boot_image(). The others are alternative boot images.
*
* @param image
* The image from which to get the boot images.
* @param num_boots
* The number of available array elements in boots and bootnodes.
* @param boots
* Returns NULL or an allocated array of pointers to boot images.
* Apply system call free(boots) to dispose it.
* @param bootnodes
* Returns NULL or an allocated array of pointers to the IsoFile nodes
* which bear the content of the boot images in boots.
* @param flag
* Bitfield for control purposes. Unused yet. Submit 0.
* @return
* 1 on success, 0 no El-Torito catalog and boot image attached,
* < 0 error.
*
* @since 0.6.32
*/
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag);
/** /**
* Removes the El-Torito bootable image. * Removes the El-Torito bootable image.
* *
@ -2382,7 +2435,7 @@ void iso_image_remove_boot_image(IsoImage *image);
* *
* For the meaning of sort weights see iso_node_set_sort_weight(). * For the meaning of sort weights see iso_node_set_sort_weight().
* That function cannot be applied to the emerging boot catalog because * That function cannot be applied to the emerging boot catalog because
* it is not represented by an IsoNode. * it is not represented by an IsoFile.
* *
* @param image * @param image
* The image to manipulate. * The image to manipulate.
@ -2415,6 +2468,19 @@ int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight);
*/ */
int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id); int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id);
/**
* Get the platform ID value. See el_torito_set_boot_platform_id().
*
* @param bootimg
* The image to inquire
* @return
* 0 - 255 : The platform ID
* < 0 : error
*
* @since 0.6.32
*/
int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg);
/** /**
* Sets the load segment for the initial boot image. This is only for * Sets the load segment for the initial boot image. This is only for
* no emulation boot images, and is a NOP for other image types. * no emulation boot images, and is a NOP for other image types.
@ -2423,6 +2489,19 @@ int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id);
*/ */
void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment); void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment);
/**
* Get the load segment value. See el_torito_set_load_seg().
*
* @param bootimg
* The image to inquire
* @return
* 0 - 65535 : The load segment value
* < 0 : error
*
* @since 0.6.32
*/
int el_torito_get_load_seg(ElToritoBootImage *bootimg);
/** /**
* Sets the number of sectors (512b) to be load at load segment during * Sets the number of sectors (512b) to be load at load segment during
* the initial boot procedure. This is only for * the initial boot procedure. This is only for
@ -2432,6 +2511,19 @@ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment);
*/ */
void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors); void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors);
/**
* Get the load size. See el_torito_set_load_size().
*
* @param bootimg
* The image to inquire
* @return
* 0 - 65535 : The load size value
* < 0 : error
*
* @since 0.6.32
*/
int el_torito_get_load_size(ElToritoBootImage *bootimg);
/** /**
* Marks the specified boot image as not bootable * Marks the specified boot image as not bootable
* *
@ -2439,6 +2531,18 @@ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors);
*/ */
void el_torito_set_no_bootable(ElToritoBootImage *bootimg); void el_torito_set_no_bootable(ElToritoBootImage *bootimg);
/**
* Get the bootability flag. See el_torito_set_no_bootable().
*
* @param bootimg
* The image to inquire
* @return
* 0 = not bootable, 1 = bootable , <0 = error
*
* @since 0.6.32
*/
int el_torito_get_bootable(ElToritoBootImage *bootimg);
/** /**
* Specifies that this image needs to be patched. This involves the writing * 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. * of a 56 bytes boot information table at offset 8 of the boot image file.
@ -2454,6 +2558,10 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
* Specifies options for ISOLINUX or GRUB boot images. This should only be used * Specifies options for ISOLINUX or GRUB boot images. This should only be used
* if the type of boot image is known. * 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 * @param options
* bitmask style flag. The following values are defined: * bitmask style flag. The following values are defined:
* *
@ -5479,6 +5587,9 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
/** Trying to use an invalid file as boot image (FAILURE,HIGH, -68) */ /** Trying to use an invalid file as boot image (FAILURE,HIGH, -68) */
#define ISO_BOOT_IMAGE_NOT_VALID 0xE830FFBB #define ISO_BOOT_IMAGE_NOT_VALID 0xE830FFBB
/** Too many boot images (FAILURE,HIGH, -69) */
#define ISO_BOOT_IMAGE_OVERFLOW 0xE830FFBA
/** /**
* Error on file operation (FAILURE,HIGH, -128) * Error on file operation (FAILURE,HIGH, -128)
* (take a look at more specified error codes below) * (take a look at more specified error codes below)

View File

@ -153,6 +153,8 @@ const char *iso_error_to_msg(int errcode)
return "Try to set the boot image of an already bootable image"; return "Try to set the boot image of an already bootable image";
case ISO_BOOT_IMAGE_NOT_VALID: case ISO_BOOT_IMAGE_NOT_VALID:
return "Trying to use an invalid file as boot image"; return "Trying to use an invalid file as boot image";
case ISO_BOOT_IMAGE_OVERFLOW:
return "Too many boot images added";
case ISO_FILE_ERROR: case ISO_FILE_ERROR:
return "Error on file operation"; return "Error on file operation";
case ISO_FILE_ALREADY_OPENED: case ISO_FILE_ALREADY_OPENED:

View File

@ -134,11 +134,11 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
memcpy(buf, t->system_area_data, 16 * BLOCK_SIZE); memcpy(buf, t->system_area_data, 16 * BLOCK_SIZE);
} else if (t->catalog != NULL && } else if (t->catalog != NULL &&
(t->catalog->image->isolinux_options & 0x0a) == 0x02) { (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) {
/* Check for isolinux image with magic number of 3.72 and produce /* Check for isolinux image with magic number of 3.72 and produce
an MBR from our built-in template. (Deprecated since 31 Mar 2010) an MBR from our built-in template. (Deprecated since 31 Mar 2010)
*/ */
ret = make_isohybrid_mbr(t->bootimg->sections[0].block, ret = make_isohybrid_mbr(t->bootsrc[0]->sections[0].block,
&img_blocks, (char*)buf, 0); &img_blocks, (char*)buf, 0);
if (ret != 1) { if (ret != 1) {
/* error, it should never happen */ /* error, it should never happen */
@ -159,7 +159,7 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
*/ */
return ISO_ISOLINUX_CANT_PATCH; return ISO_ISOLINUX_CANT_PATCH;
} }
ret = make_isolinux_mbr(&img_blocks, t->bootimg->sections[0].block, ret = make_isolinux_mbr(&img_blocks, t->bootsrc[0]->sections[0].block,
(uint32_t) 0, 64, 32, 0, 1, 0x17, buf, 1); (uint32_t) 0, 64, 32, 0, 1, 0x17, buf, 1);
if (ret != 1) if (ret != 1)
return ret; return ret;