New API call iso_write_opts_set_disc_label(),

new system area type 3 = SUN Disk Label
This commit is contained in:
Thomas Schmitt 2010-11-05 15:34:42 +01:00
parent ea8da1f7d3
commit a488f8fb14
5 changed files with 263 additions and 36 deletions

View File

@ -107,7 +107,7 @@ void ecma119_image_free(Ecma119Image *t)
free(t->writers);
if (t->partition_root != NULL)
ecma119_node_free(t->partition_root);
for (i = 0; i < 4; i++)
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
if (t->appended_partitions[i] != NULL)
free(t->appended_partitions[i]);
@ -1299,13 +1299,20 @@ static int finish_libjte(Ecma119Image *target)
static int write_mbr_partition_file(Ecma119Image *target, char *path,
uint32_t blocks, int flag)
uint32_t prepad, uint32_t blocks, int flag)
{
FILE *fp = NULL;
uint32_t i;
uint8_t buf[BLOCK_SIZE];
int ret;
memset(buf, 0, BLOCK_SIZE);
for (i = 0; i < prepad; i++) {
ret = iso_write(target, buf, BLOCK_SIZE);
if (ret < 0)
return ret;
}
fp = fopen(path, "rb");
if (fp == NULL)
return ISO_BAD_PARTITION_FILE;
@ -1325,7 +1332,7 @@ static int write_mbr_partition_file(Ecma119Image *target, char *path,
return ret;
}
}
if (fp != NULL)
fclose(fp);
return ISO_SUCCESS;
}
@ -1334,7 +1341,7 @@ static int write_mbr_partition_file(Ecma119Image *target, char *path,
static
void *write_function(void *arg)
{
int res;
int res, first_partition = 1, last_partition = 0, sa_type;
size_t i;
IsoImageWriter *writer;
@ -1358,16 +1365,26 @@ void *write_function(void *arg)
}
/* Append partition data */
for (i = 0; i < 4; i++) {
sa_type = (target->system_area_options >> 2) & 0x3f;
if (sa_type == 0) { /* MBR */
first_partition = 1;
last_partition = 4;
} else if (sa_type == 3) { /* SUN Disk Label */
first_partition = 2;
last_partition = 8;
}
for (i = first_partition - 1; i <= last_partition - 1; i++) {
if (target->appended_partitions[i] == NULL)
continue;
if (target->appended_partitions[i][0] == 0)
continue;
res = write_mbr_partition_file(target, target->appended_partitions[i],
target->appended_part_prepad[i],
target->appended_part_size[i], 0);
if (res < 0)
goto write_error;
}
/* Transplant checksum buffer from Ecma119Image to IsoImage */
transplant_checksum_buffer(target, 0);
@ -1520,6 +1537,7 @@ static
int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
{
int ret, i, voldesc_size, nwriters, image_checksums_mad = 0, tag_pos;
int sa_type;
Ecma119Image *target;
IsoImageWriter *writer;
int el_torito_writer_index = -1, file_src_writer_index = -1;
@ -1615,8 +1633,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
} else {
system_area_options = opts->system_area_options & 0xfc;
}
if ((system_area_options & 0xfc) != 0)
for (i = 0; i < 4; i++)
sa_type = (system_area_options >> 2) & 0x3f;
if (sa_type != 0 && sa_type != 3)
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
if (opts->appended_partitions[i] != NULL)
return ISO_NON_MBR_SYS_AREA;
@ -1708,7 +1727,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->mipsel_p_vaddr = 0;
target->mipsel_p_filesz = 0;
for (i = 0; i < 4; i++) {
for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
target->appended_partitions[i] = NULL;
if (opts->appended_partitions[i] != NULL) {
target->appended_partitions[i] =
strdup(opts->appended_partitions[i]);
@ -1716,9 +1736,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
return ISO_OUT_OF_MEM;
target->appended_part_types[i] = opts->appended_part_types[i];
}
target->appended_part_prepad[i] = 0;
target->appended_part_start[i] = target->appended_part_size[i] = 0;
}
strcpy(target->ascii_disc_label, opts->ascii_disc_label);
/*
* 2. Based on those options, create needed writers: iso, joliet...
@ -2306,8 +2327,9 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
#endif /* Libisofs_with_libjtE */
wopts->tail_blocks = 0;
for (i = 0; i < 4; i++)
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
wopts->appended_partitions[i] = NULL;
wopts->ascii_disc_label[0] = 0;
*opts = wopts;
return ISO_SUCCESS;
@ -2323,7 +2345,7 @@ void iso_write_opts_free(IsoWriteOpts *opts)
free(opts->output_charset);
if (opts->system_area_data != NULL)
free(opts->system_area_data);
for (i = 0; i < 4; i++)
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
if (opts->appended_partitions[i] != NULL)
free(opts->appended_partitions[i]);
@ -2806,7 +2828,7 @@ int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks)
int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
uint8_t partition_type, char *image_path, int flag)
{
if (partition_number < 1 || partition_number > 4)
if (partition_number < 1 || partition_number > ISO_MAX_PARTITIONS)
return ISO_BAD_PARTITION_NO;
if (opts->appended_partitions[partition_number - 1] != NULL)
@ -2819,3 +2841,10 @@ int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
return ISO_SUCCESS;
}
int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label)
{
strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1);
opts->ascii_disc_label[ISO_DISC_LABEL_SIZE - 1] = 0;
return ISO_SUCCESS;
}

View File

@ -32,6 +32,26 @@
*/
#define ISO_EXTENT_SIZE 0xFFFFF800
/*
* The maximum number of partition images that can be registered. Depending
* on the system area type, the effectively usable number may be smaller or
* even 0.
*/
#define ISO_MAX_PARTITIONS 8
/*
* The cylindersize with SUN Disk Label
* (512 bytes/sector, 640 sectors/head, 1 head/cyl = 320 KiB).
* Expressed in ECMA-119 blocks of 2048 bytes/block.
*/
#define ISO_SUN_CYL_SIZE 160
/*
* Maximum length of a disc label text plus 1.
*/
#define ISO_DISC_LABEL_SIZE 129
/**
* Holds the options for the image generation.
*/
@ -337,8 +357,12 @@ struct iso_write_opts {
/* Eventual disk file paths of prepared images which shall be appended
after the ISO image and described by partiton table entries in a MBR
*/
char *appended_partitions[4];
uint8_t appended_part_types[4];
char *appended_partitions[ISO_MAX_PARTITIONS];
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
*/
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
};
typedef struct ecma119_image Ecma119Image;
@ -601,11 +625,14 @@ struct ecma119_image
uint32_t mipsel_p_vaddr;
uint32_t mipsel_p_filesz;
char *appended_partitions[4];
uint8_t appended_part_types[4];
char *appended_partitions[ISO_MAX_PARTITIONS];
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
/* Counted in blocks of 2048 */
uint32_t appended_part_start[4];
uint32_t appended_part_size[4];
uint32_t appended_part_prepad[ISO_MAX_PARTITIONS];
uint32_t appended_part_start[ISO_MAX_PARTITIONS];
uint32_t appended_part_size[ISO_MAX_PARTITIONS];
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
};

View File

@ -1751,6 +1751,9 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
*
* If system area data are given or options bit0 is set, then bit1 of
* el_torito_set_isolinux_options() is automatically disabled.
*
* @param opts
* The option set to be manipulated.
* @param data
* Either NULL or 32 kB of data. Do not submit less bytes !
* @param options
@ -1780,6 +1783,13 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* iso_image_add_mips_boot_file() will be activated.
* This will overwrite the first 512 bytes of the submitted
* data.
* @since 0.6.40
* 3= SUN Disk Label for SUN SPARC
* Submit up to 7 SPARC boot images by
* iso_write_opts_set_partition_img() for partition numbers 2
* to 8.
* This will overwrite the first 512 bytes of the submitted
* data.
* @param flag
* bit0 = invalidate any attached system area data. Same as data == NULL
* (This re-activates eventually loaded image System Area data.
@ -1793,6 +1803,22 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768],
int options, int flag);
/**
* Set a name for the system area. This setting is ignored unless system area
* type 3 "SUN Disk Label" is in effect by iso_write_opts_set_system_area().
* In this case it will replace the default text at the start of the image:
* "CD-ROM Disc with Sun sparc boot created by libisofs"
*
* @param opts
* The option set to be manipulated.
* @param label
* A text of up to 128 characters.
* @return
* ISO_SUCCESS or error
* @since 0.6.40
*/
int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label);
/**
* Explicitely set the four timestamps of the emerging Primary Volume
* Descriptor. Default with all parameters is 0.
@ -1936,24 +1962,33 @@ int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle);
*/
int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks);
/**
* Cause an arbitrary data file to be appended to the ISO image and to be
* described by a partition table entry in an MBR at the start of the
* ISO image.
* described by a partition table entry in an MBR or SUN Disk Label at the
* start of the ISO image.
* The partition entry will bear the size of the image file rounded up to
* the next multiple of 2048 bytes.
* MBR or SUN Disk Label are selected by iso_write_opts_set_system_area()
* system area type: 0 selects MBR partition table. 3 selects a SUN partition
* table with 320 kB start alignment.
*
* @param opts
* The option set to be manipulated.
* @param partition_number
* Depicts the partition table entry which shall describe the
* appended image. Range 1 to 4.
* 1 will cause the whole ISO image to be unclaimable space before
* partition 1.
* appended image.
* Range with MBR: 1 to 4. 1 will cause the whole ISO image to be
* unclaimable space before partition 1.
* Range with SUN Disk Label: 2 to 8.
* @param image_path
* File address in the local file system.
* With SUN Disk Label: an empty name causes the partition to become
* a copy of the next lower partition.
* @param image_type
* The partition type. E.g. FAT12 = 0x01 , FAT16 = 0x06,
* The MBR partition type. E.g. FAT12 = 0x01 , FAT16 = 0x06,
* Linux Native Partition = 0x83. See fdisk command L.
* This parameter is ignored with SUN Disk Label.
* @return
* ISO_SUCCESS or error
*

View File

@ -266,6 +266,7 @@ iso_write_opts_set_default_gid;
iso_write_opts_set_default_timestamp;
iso_write_opts_set_default_uid;
iso_write_opts_set_dir_rec_mtime;
iso_write_opts_set_disc_label;
iso_write_opts_set_fifo_size;
iso_write_opts_set_hardlinks;
iso_write_opts_set_iso1999;

View File

@ -19,6 +19,7 @@
#include "ecma119_tree.h"
#include "image.h"
#include "messages.h"
#include "ecma119.h"
#include <string.h>
#include <stdio.h>
@ -79,13 +80,16 @@ void iso_compute_cyl_head_sec(uint32_t *img_blocks, int hpc, int sph,
*/
int iso_compute_append_partitions(Ecma119Image *t, int flag)
{
int ret, i;
uint32_t pos, size;
int ret, i, sa_type;
uint32_t pos, size, add_pos = 0;
struct stat stbuf;
sa_type = (t->system_area_options >> 2) & 0x3f;
pos = (t->vol_space_size + t->ms_block);
for (i = 0; i < 4; i++) {
for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
if (t->appended_partitions[i] == NULL)
continue;
if (t->appended_partitions[i][0] == 0)
continue;
ret = stat(t->appended_partitions[i], &stbuf);
if (ret == -1)
@ -93,10 +97,13 @@ int iso_compute_append_partitions(Ecma119Image *t, int flag)
if (! S_ISREG(stbuf.st_mode))
return ISO_BAD_PARTITION_FILE;
size = ((stbuf.st_size + 2047) / 2048);
t->appended_part_start[i] = pos;
if (sa_type == 3 && (pos % ISO_SUN_CYL_SIZE))
add_pos = ISO_SUN_CYL_SIZE - (pos % ISO_SUN_CYL_SIZE);
t->appended_part_prepad[i] = add_pos;
t->appended_part_start[i] = pos + add_pos;
t->appended_part_size[i] = size;
pos += size;
t->total_size += size * 2048;
pos += add_pos + size;
t->total_size += (add_pos + size) * 2048;
}
return ISO_SUCCESS;
}
@ -565,9 +572,122 @@ static int make_mipsel_boot_block(Ecma119Image *t, uint8_t *buf, int flag)
}
/* The following two functions were implemented according to
doc/boot_sectors.txt section "SUN Disk Label and boot images" which
was derived by Thomas Schmitt from
cdrtools-2.01.01a77/mkisofs/sunlabel.h
cdrtools-2.01.01a77/mkisofs/mkisofs.8
by Joerg Schilling
Both functions are entirely under copyright (C) 2010 Thomas Schmitt.
*/
/* @parm flag bit0= copy from next lower valid partition table entry
*/
static int write_sun_partition_entry(int partition_number,
char *appended_partitions[],
uint32_t partition_offset[], uint32_t partition_size[],
uint32_t cyl_size, uint8_t *buf, int flag)
{
uint8_t *wpt;
int read_idx, i;
if (partition_number < 1 || partition_number > 8)
return ISO_ASSERT_FAILURE;
/* 142 - 173 | ========== | 8 partition entries of 4 bytes */
wpt = buf + 142 + (partition_number - 1) * 4;
if (partition_number == 1)
iso_msb(wpt, 4, 2); /* 4 = User partition */
else
iso_msb(wpt, 2, 2); /* 2 = Root partition with boot image */
iso_msb(wpt + 2, 0x10, 2); /* Permissions: 0x10 = read-only */
/* 444 - 507 | ========== | Partition table */
wpt = buf + 444 + (partition_number - 1) * 8;
read_idx = partition_number - 1;
if (flag & 1) {
/* Search next lower valid partition table entry. #1 is default */
for (read_idx = partition_number - 2; read_idx > 0; read_idx--)
if (appended_partitions[read_idx] != NULL)
if (appended_partitions[read_idx][0] != 0)
break;
}
iso_msb(wpt, partition_offset[read_idx] / (uint32_t) ISO_SUN_CYL_SIZE, 4);
iso_msb(wpt + 4, partition_size[read_idx] * 4, 4);
/* 510 - 511 | checksum | The result of exoring 2-byte words 0 to 254 */
buf[510] = buf[511] = 0;
for (i = 0; i < 510; i += 2) {
buf[510] ^= buf[i];
buf[511] ^= buf[i + 1];
}
return ISO_SUCCESS;
}
/**
* Write SUN Disk Label with ISO in partition 1 and unused 2 to 8
*/
static int make_sun_disk_label(Ecma119Image *t, uint8_t *buf, int flag)
{
int ret;
/* Bytes 512 to 32767 may come from image or external file */
memset(buf, 0, 512);
/* 0 - 127 | label | ASCII Label */
if (t->ascii_disc_label[0])
strncpy((char *) buf, t->ascii_disc_label, 128);
else
strcpy((char *) buf,
"CD-ROM Disc with Sun sparc boot created by libisofs");
/* 128 - 131 | 1 | Layout version */
iso_msb(buf + 128, 1, 4);
/* 140 - 141 | 8 | Number of partitions */
iso_msb(buf + 140, 8, 2);
/* 188 - 191 | 0x600ddeee | vtoc sanity */
iso_msb(buf + 188, 0x600ddeee, 4);
/* 420 - 421 | 350 | Rotations per minute */
iso_msb(buf + 420, 350, 2);
/* 422 - 423 | 2048 | Number of physical cylinders (fixely 640 MB) */
iso_msb(buf + 422, 2048, 2);
/* 430 - 431 | 1 | interleave factor */
iso_msb(buf + 430, 1, 2);
/* 432 - 433 | 2048 | Number of data cylinders (fixely 640 MB) */
iso_msb(buf + 432, 2048, 2);
/* 436 - 437 | 1 | Number of heads per cylinder (1 cyl = 320 kB)*/
iso_msb(buf + 436, 1, 2);
/* 438 - 439 | 640 | Number of sectors per head (1 head = 320 kB) */
iso_msb(buf + 438, 640, 2);
/* 508 - 509 | 0xdabe | Magic Number */
iso_msb(buf + 508, 0xdabe, 2);
/* Set partition 1 to describe ISO image and compute checksum */
t->appended_part_start[0] = 0;
t->appended_part_size[0] = t->curblock;
ret = write_sun_partition_entry(1, t->appended_partitions,
t->appended_part_start, t->appended_part_size,
ISO_SUN_CYL_SIZE, buf, 0);
return ISO_SUCCESS;
}
int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
{
int ret, int_img_blocks, sa_type, i, will_append = 0;
int first_partition = 1, last_partition = 4;
uint32_t img_blocks;
if ((t == NULL) || (buf == NULL)) {
@ -578,7 +698,11 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
memset(buf, 0, 16 * BLOCK_SIZE);
sa_type = (t->system_area_options >> 2) & 0x3f;
for (i = 0; i < 4; i++)
if (sa_type == 3) {
first_partition = 2;
last_partition = 8;
}
for (i = first_partition - 1; i <= last_partition - 1; i++)
if (t->appended_partitions[i] != NULL) {
will_append = 1;
break;
@ -648,6 +772,10 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
if (ret < 0)
return ret;
}
} else if (sa_type == 3) {
ret = make_sun_disk_label(t, buf, 0);
if (ret != ISO_SUCCESS)
return ret;
}
if (t->partition_offset > 0 && sa_type == 0) {
@ -661,13 +789,20 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
}
/* This eventually overwrites the partition table entries made so far */
for (i = 0; i < 4; i++) {
for (i = first_partition - 1; i <= last_partition - 1; i++) {
if (t->appended_partitions[i] == NULL)
continue;
if (sa_type == 3) {
ret = write_sun_partition_entry(i + 1, t->appended_partitions,
t->appended_part_start, t->appended_part_size,
ISO_SUN_CYL_SIZE,
buf, t->appended_partitions[i][0] == 0);
} else {
ret = write_mbr_partition_entry(i + 1, t->appended_part_types[i],
t->appended_part_start[i], t->appended_part_size[i],
t->partition_secs_per_head, t->partition_heads_per_cyl,
buf, 0);
}
if (ret < 0)
return ret;
}