diff --git a/libisofs/eltorito.c b/libisofs/eltorito.c index 9ef4a87..b0aab67 100644 --- a/libisofs/eltorito.c +++ b/libisofs/eltorito.c @@ -123,6 +123,36 @@ int el_torito_get_bootable(ElToritoBootImage *bootimg) return !!bootimg->bootable; } +/* API */ +int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]) +{ + memcpy(bootimg->id_string, id_string, 28); + return 1; +} + +/* API */ +int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]) +{ + + memcpy(id_string, bootimg->id_string, 28); + return 1; +} + +/* API */ +int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]) +{ + memcpy(bootimg->selection_crit, crit, 20); + return 1; +} + +/* API */ +int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]) +{ + + memcpy(crit, bootimg->selection_crit, 20); + return 1; +} + /** * 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. @@ -376,7 +406,8 @@ int create_image(IsoImage *image, const char *image_path, boot->load_seg = 0; boot->load_size = load_sectors; boot->platform_id = 0; /* 80x86 */ - + memset(boot->id_string, 0, sizeof(boot->id_string)); + memset(boot->selection_crit, 0, sizeof(boot->selection_crit)); if (bootimg) { *bootimg = boot; } @@ -656,7 +687,8 @@ struct catalog_stream }; static void -write_validation_entry(uint8_t *buf, uint8_t platform_id) +write_validation_entry(uint8_t *buf, uint8_t platform_id, + uint8_t id_string[24]) { size_t i; int checksum; @@ -665,9 +697,9 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id) (struct el_torito_validation_entry*)buf; ve->header_id[0] = 1; ve->platform_id[0] = platform_id; + memcpy(ve->id_string, id_string, sizeof(ve->id_string)); ve->key_byte1[0] = 0x55; ve->key_byte2[0] = 0xAA; - /* calculate the checksum, to ensure sum of all words is 0 */ checksum = 0; for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) { @@ -677,7 +709,8 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id) } static void -write_section_header(uint8_t *buf, Ecma119Image *t, int idx) { +write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries) +{ int pi; char *id_string; @@ -687,17 +720,11 @@ write_section_header(uint8_t *buf, Ecma119Image *t, int idx) { /* 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; + e->num_entries[0] = num_entries & 0xff; + e->num_entries[1] = (num_entries >> 8) & 0xff;; 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 ..." -*/ - + memcpy(id_string, t->catalog->bootimages[idx]->id_string, + sizeof(e->id_string)); } /** @@ -720,18 +747,25 @@ write_section_entry(uint8_t *buf, Ecma119Image *t, int idx) se->system_type[0] = img->partition_type; iso_lsb(se->sec_count, img->load_size, 2); iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4); + se->selec_criteria[0] = img->selection_crit[0]; + memcpy(se->vendor_sc, img->selection_crit + 1, 19); } static int catalog_open(IsoStream *stream) { - int i; + int i, j, k, num_entries; struct catalog_stream *data; + uint8_t *wpt; + struct el_torito_boot_catalog *cat; + struct el_torito_boot_image **boots; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; + cat = data->target->catalog; + boots = cat->bootimages; if (data->offset != -1) { return ISO_FILE_ALREADY_OPENED; @@ -741,16 +775,35 @@ int catalog_open(IsoStream *stream) /* fill the buffer with the catalog contents */ write_validation_entry(data->buffer, - data->target->catalog->bootimages[0]->platform_id); + boots[0]->platform_id, boots[0]->id_string); /* write default entry = first boot image */ 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); + wpt = data->buffer + 64; + for (i = 1; i < cat->num_bootimages; ) { + /* Look ahead and put images of same platform_id and id_string + into the same section */ + for (j = i + 1; j < cat->num_bootimages; j++) { + if (boots[i]->platform_id != boots[j]->platform_id) + break; + for (k = 0; k < sizeof(boots[i]->selection_crit); k++) + if (boots[i]->selection_crit[k] != boots[j]->selection_crit[k]) + break; + if (k < sizeof(boots[i]->selection_crit)) + break; + } + num_entries = j - i; + + write_section_header(wpt, data->target, i, num_entries); + wpt += 32; + for (j = 0; j < num_entries; j++) { + write_section_entry(wpt, data->target, i); + wpt += 32; + i++; + } } data->offset = 0; return ISO_SUCCESS; diff --git a/libisofs/eltorito.h b/libisofs/eltorito.h index d63b99c..65bc58c 100644 --- a/libisofs/eltorito.h +++ b/libisofs/eltorito.h @@ -64,6 +64,8 @@ struct el_torito_boot_image { /* Byte 1 of Validation Entry or Section Header Entry: 0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */ uint8_t platform_id; + uint8_t id_string[28]; + uint8_t selection_crit[20]; }; /** El-Torito, 2.1 */ diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index b0dee63..267bb58 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -282,6 +282,8 @@ typedef struct /* ts B00419 */ int num_bootimgs; unsigned char platform_ids[Libisofs_max_boot_imageS]; + unsigned char id_strings[Libisofs_max_boot_imageS][28]; + unsigned char selection_crits[Libisofs_max_boot_imageS][20]; unsigned char boot_flags[Libisofs_max_boot_imageS]; /* bit0= bootable */ unsigned char media_types[Libisofs_max_boot_imageS]; unsigned char partition_types[Libisofs_max_boot_imageS]; @@ -2238,12 +2240,16 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) /* The Default Entry is declared mandatory */ data->num_bootimgs = 1; data->platform_ids[0] = ve->platform_id[0]; + memcpy(data->id_strings[0], ve->id_string, 24); + memset(data->id_strings[0] + 24, 0, 4); data->boot_flags[0] = entry->boot_indicator[0] ? 1 : 0; 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); + /* The Default Entry has no selection criterion */ + memset(data->selection_crits[0], 0, 20); /* ts B00420 : Read eventual more entries from the boot catalog */ last_done = 0; @@ -2262,12 +2268,15 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) entry = (struct el_torito_section_entry *)(buffer + rx); idx = data->num_bootimgs; data->platform_ids[idx] = sh->platform_id[0]; + memcpy(data->id_strings[idx], sh->id_string, 28); 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->selection_crits[idx][0] = entry->selec_criteria[0]; + memcpy(data->selection_crits[idx] + 1, entry->vendor_sc, 19); data->num_bootimgs++; } } @@ -3137,12 +3146,14 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, boot_image->load_seg = data->load_segs[idx]; boot_image->load_size = data->load_sizes[idx]; boot_image->platform_id = data->platform_ids[idx]; + memcpy(boot_image->id_string, data->id_strings[idx], 28); + memcpy(boot_image->selection_crit, data->selection_crits, 20); catalog->bootimages[catalog->num_bootimages] = boot_image; catalog->num_bootimages++; } for ( ; idx < Libisofs_max_boot_imageS; idx++) - catalog->bootimages[idx] = NULL; + catalog->bootimages[idx] = NULL; image->bootcat = catalog; } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 3be6c13..f2cf88a 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -2543,6 +2543,77 @@ void el_torito_set_no_bootable(ElToritoBootImage *bootimg); */ int el_torito_get_bootable(ElToritoBootImage *bootimg); +/** + * Set the id_string of the Validation Entry resp. Sector Header Entry which + * will govern the boot image Section Entry in the El Torito Catalog. + * + * @param bootimg + * The image to manipulate. + * @param id_string + * The first boot image puts 24 bytes of ID string into the Validation + * Entry, where they shall "identify the manufacturer/developer of + * the CD-ROM". + * Further boot images put 28 bytes into their Section Header. + * El Torito 1.0 states that "If the BIOS understands the ID string, it + * may choose to boot the * system using one of these entries in place + * of the INITIAL/DEFAULT entry." (The INITIAL/DEFAULT entry points to the + * first boot image.) + * @return + * 1 = ok , <0 = error + * + * @since 0.6.32 + */ +int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]); + +/** + * Get the id_string as of el_torito_set_id_string(). + * + * @param bootimg + * The image to inquire + * @param id_string + * Returns 28 bytes of id string + * @return + * 1 = ok , <0 = error + * + * @since 0.6.32 + */ +int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]); + +/** + * Set the Selection Criteria of a boot image. + * + * @param bootimg + * The image to manipulate. + * @param crit + * The first boot image has no selection criteria. They will be ignored. + * Further boot images put 1 byte of Selection Criteria Type and 19 + * bytes of data into their Section Entry. + * El Torito 1.0 states that "The format of the selection criteria is + * a function of the BIOS vendor. In the case of a foreign language + * BIOS three bytes would be used to identify the language". + * Type byte == 0 means "no criteria", + * type byte == 1 means "Language and Version Information (IBM)". + * @return + * 1 = ok , <0 = error + * + * @since 0.6.32 + */ +int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]); + +/** + * Get the Selection Criteria bytes as of el_torito_set_selection_crit(). + * + * @param bootimg + * The image to inquire + * @param id_string + * Returns 20 bytes of type and data + * @return + * 1 = ok , <0 = error + * + * @since 0.6.32 + */ +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.