New API call iso_write_opts_set_hfsp_block_size().

This commit is contained in:
Thomas Schmitt 2012-06-27 20:39:57 +02:00
parent 7e49fb553b
commit 2d441cca5d
8 changed files with 317 additions and 168 deletions

View File

@ -1920,7 +1920,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->hfsplus_blessed[i] != NULL) if (target->hfsplus_blessed[i] != NULL)
iso_node_ref(target->hfsplus_blessed[i]); iso_node_ref(target->hfsplus_blessed[i]);
} }
target->apm_block_size = 512; target->apm_block_size = opts->apm_block_size;
target->hfsp_block_size = opts->hfsp_block_size;
target->hfsp_cat_node_size = 0;
target->hfsp_iso_block_fac = 0;
target->apm_req_count = 0; target->apm_req_count = 0;
target->apm_req_flags = 0; target->apm_req_flags = 0;
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++) for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
@ -2356,6 +2359,13 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
iso_image_free_checksums(target->image, 0); iso_image_free_checksums(target->image, 0);
image_checksums_mad = 0; image_checksums_mad = 0;
if (target->apm_block_size == 0) {
if (target->gpt_req_count)
target->apm_block_size = 2048; /* Combinable with GPT */
else
target->apm_block_size = 512; /* Mountable on Linux */
}
/* ensure the thread is created joinable */ /* ensure the thread is created joinable */
pthread_attr_init(&(target->th_attr)); pthread_attr_init(&(target->th_attr));
pthread_attr_setdetachstate(&(target->th_attr), PTHREAD_CREATE_JOINABLE); pthread_attr_setdetachstate(&(target->th_attr), PTHREAD_CREATE_JOINABLE);
@ -2739,6 +2749,8 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->untranslated_name_len = 0; wopts->untranslated_name_len = 0;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
wopts->hfsp_serial_number[i] = 0; wopts->hfsp_serial_number[i] = 0;
wopts->apm_block_size = 0;
wopts->hfsp_block_size = 0;
*opts = wopts; *opts = wopts;
return ISO_SUCCESS; return ISO_SUCCESS;
@ -3403,4 +3415,18 @@ int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts,
memcpy(opts->hfsp_serial_number, serial_number, 8); memcpy(opts->hfsp_serial_number, serial_number, 8);
return ISO_SUCCESS; return ISO_SUCCESS;
} }
int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts,
int hfsp_block_size, int apm_block_size)
{
if (hfsp_block_size != 0 && hfsp_block_size != 512 &&
hfsp_block_size != 2048)
return ISO_BOOT_HFSP_BAD_BSIZE;
opts->hfsp_block_size = hfsp_block_size;
if (apm_block_size != 0 && apm_block_size != 512 && apm_block_size != 2048)
return ISO_BOOT_HFSP_BAD_BSIZE;
opts->apm_block_size = apm_block_size;
return ISO_SUCCESS;
}

View File

@ -477,6 +477,14 @@ struct iso_write_opts {
*/ */
uint8_t hfsp_serial_number[8]; uint8_t hfsp_serial_number[8];
/* Allocation block size of HFS+ : 0= auto , 512, or 2048
*/
int hfsp_block_size;
/* Block size of and in APM : 0= auto , 512, or 2048
*/
int apm_block_size;
}; };
typedef struct ecma119_image Ecma119Image; typedef struct ecma119_image Ecma119Image;
@ -819,6 +827,22 @@ struct ecma119_image
/* See IsoImage and libisofs.h */ /* See IsoImage and libisofs.h */
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]; IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
/* Block sizes come from write options.
Only change a block size if it is 0. Set only to 512 or 2048.
If it stays 0 then it will become 512 or 2048 in time.
*/
/* Blocksize of Apple Partition Map
May be defined to 512 or 2048 before writer thread starts.
*/
int apm_block_size;
/* Allocation block size of HFS+
May be defined to 512 or 2048 before hfsplus_writer_create().
*/
int hfsp_block_size;
int hfsp_cat_node_size; /* 2 * apm_block_size */
int hfsp_iso_block_fac; /* 2048 / apm_block_size */
/* Apple Partition Map description. To be composed during IsoImageWriter /* Apple Partition Map description. To be composed during IsoImageWriter
method ->compute_data_blocks() by calling iso_register_apm_entry(). method ->compute_data_blocks() by calling iso_register_apm_entry().
Make sure that the composing writers get registered before the Make sure that the composing writers get registered before the
@ -826,9 +850,10 @@ struct ecma119_image
*/ */
struct iso_apm_partition_request *apm_req[ISO_APM_ENTRIES_MAX]; struct iso_apm_partition_request *apm_req[ISO_APM_ENTRIES_MAX];
int apm_req_count; int apm_req_count;
/* 512 by default. May be changed to 2048 before writer thread starts. */ /* bit1= Do not fill gaps in Apple Partition Map
int apm_block_size; bit2= apm_req entries use apm_block_size in start_block and block_count.
/* bit1= Do not fill gaps in Apple Partition Map */ Normally these two parameters are counted in 2 KiB blocks.
*/
int apm_req_flags; int apm_req_flags;
/* MBR partition table description. To be composed during IsoImageWriter /* MBR partition table description. To be composed during IsoImageWriter

View File

@ -20,6 +20,16 @@
#define Libisofs_ts_debuG yes #define Libisofs_ts_debuG yes
/* Do not fill gaps in APM.
<<< provisory , rather not
# define Libisofs_hfsplus_no_gap_filL yes
*/
/* Avoid ISO block padding in hfsplus_tail_writer
<<< provisory , rather not
# define Libisofs_apm_flags_bit2 yes
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "../config.h" #include "../config.h"
@ -41,10 +51,16 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#define HFSPLUS_BLOCK_SIZE 2048 /* To be used if Ecma119.hfsplus_block_size == 0 in hfsplus_writer_create().
#define HFSPLUS_CAT_NODE_SIZE (2 * HFSPLUS_BLOCK_SIZE) It cannot be larger than 2048 because filesrc_writer aligns data file
content start to 2048.
*/
#define HFSPLUS_DEFAULT_BLOCK_SIZE 2048
/* To be used with storage allocation.
*/
#define HFSPLUS_MAX_BLOCK_SIZE 2048
#define HFSPLUS_ISO_BLOCK_FAC (2048 / HFSPLUS_BLOCK_SIZE)
#include <arpa/inet.h> #include <arpa/inet.h>
/* For these prototypes: /* For these prototypes:
@ -311,8 +327,8 @@ int create_tree(Ecma119Image *t, IsoNode *iso, uint32_t parent_id)
if (t->hfsplus_blessed[i] == iso) { if (t->hfsplus_blessed[i] == iso) {
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')", iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')",
i, cat_id, iso->name); i, cat_id, iso->name);
#endif /* Libisofs_ts_debuG */ #endif /* Libisofs_ts_debuG */
t->hfsp_bless_id[i] = cat_id; t->hfsp_bless_id[i] = cat_id;
@ -417,100 +433,141 @@ cmp_node(const void *f1, const void *f2)
return ucscmp(a, b); return ucscmp(a, b);
} }
static static
int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer) int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
{ {
Ecma119Image *t; Ecma119Image *t;
uint32_t hfsp_size; uint32_t hfsp_size, hfsp_curblock, block_fac, block_size;
if (writer == NULL) { if (writer == NULL) {
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
t = writer->target; t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f", iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f",
((double) t->curblock) * 2048.0); ((double) t->curblock) * 2048.0);
#endif #endif
hfsp_size = t->curblock * HFSPLUS_ISO_BLOCK_FAC - t->hfsp_part_start + 1; hfsp_curblock = t->curblock * block_fac;
hfsp_size = hfsp_curblock - t->hfsp_part_start + 1;
/* We need one bit for every block. */ /* We need one bit for every block. */
/* So if we allocate x blocks we have to satisfy: /* So if we allocate x blocks we have to satisfy:
8 * HFSPLUS_BLOCK_SIZE * x >= total_size + x 8 * block_size * x >= total_size + x
(8 * HFSPLUS_BLOCK_SIZE - 1) * x >= total_size (8 * block_size - 1) * x >= total_size
*/ */
t->hfsp_allocation_blocks = hfsp_size t->hfsp_allocation_blocks = hfsp_size / (8 * block_size - 1) + 1;
/ (8 * HFSPLUS_BLOCK_SIZE - 1) + 1; t->hfsp_allocation_file_start = hfsp_curblock;
t->hfsp_allocation_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC; hfsp_curblock += t->hfsp_allocation_blocks;
t->curblock += t->hfsp_allocation_blocks / HFSPLUS_ISO_BLOCK_FAC;
if (t->hfsp_allocation_blocks % HFSPLUS_ISO_BLOCK_FAC) #ifdef Libisofs_apm_flags_bit2
/* Superblock always occupies 2K */
hfsp_curblock += block_fac;
/* write_data() will need to pad up ISO block after superblock copy */
t->curblock = hfsp_curblock / block_fac;
if (hfsp_curblock % block_fac)
t->curblock++; t->curblock++;
#else /* Libisofs_apm_flags_bit2 */
/* write_data() will need to pad up ISO block before superblock copy */
t->curblock = hfsp_curblock / block_fac;
if (hfsp_curblock % block_fac)
t->curblock++;
hfsp_curblock = t->curblock * block_fac;
/* Superblock always occupies 2K */
hfsp_curblock += block_fac;
t->curblock++; t->curblock++;
#endif /* ! Libisofs_apm_flags_bit4 */
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f", iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f",
((double) t->curblock) * 2048.0); ((double) hfsp_curblock) * block_size);
#endif #endif
t->hfsp_total_blocks = t->curblock * HFSPLUS_ISO_BLOCK_FAC t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start;
- t->hfsp_part_start;
t->apm_block_size = HFSPLUS_BLOCK_SIZE; #ifdef Libisofs_hfsplus_no_gap_filL
return iso_quick_apm_entry(t, t->hfsp_part_start / HFSPLUS_ISO_BLOCK_FAC, /* <<< test B20625 : leave out gap filling */
t->hfsp_total_blocks / HFSPLUS_ISO_BLOCK_FAC + t->apm_req_flags |= 2;
!!(t->hfsp_total_blocks % HFSPLUS_ISO_BLOCK_FAC), #endif /* Libisofs_hfsplus_no_gap_filL */
#ifdef Libisofs_apm_flags_bit2
t->apm_req_flags |= 4;
return iso_quick_apm_entry(t, t->hfsp_part_start,
t->hfsp_total_blocks,
"HFSPLUS_Hybrid", "Apple_HFS"); "HFSPLUS_Hybrid", "Apple_HFS");
#else /* Libisofs_apm_flags_bit2 */
return iso_quick_apm_entry(t, t->hfsp_part_start / block_fac,
t->hfsp_total_blocks / block_fac +
!!(t->hfsp_total_blocks % block_fac),
"HFSPLUS_Hybrid", "Apple_HFS");
#endif /* ! Libisofs_apm_flags_bit2 */
} }
static static
int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer) int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
{ {
Ecma119Image *t; Ecma119Image *t;
uint32_t i, link_blocks; uint32_t i, link_blocks, hfsp_curblock;
uint32_t block_fac, cat_node_size, block_size;
if (writer == NULL) { if (writer == NULL) {
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
t = writer->target; t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
cat_node_size = t->hfsp_cat_node_size;
iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes); iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
t->hfsp_part_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC; t->hfsp_part_start = t->curblock * block_fac;
t->curblock++; hfsp_curblock = t->curblock * block_fac;
t->hfsp_catalog_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC; /* Superblock always occupies 2K */
hfsp_curblock += block_fac;
/* ts B20623 was: t->hfsp_catalog_file_start = hfsp_curblock;
t->curblock += 2 * t->hfsp_nnodes;
/*
hfsp_curblock += (t->hfsp_nnodes * cat_node_size + block_size - 1) / block_size;
*/ */
t->curblock += (t->hfsp_nnodes * HFSPLUS_CAT_NODE_SIZE + 2047) / 2048; hfsp_curblock += 2 * t->hfsp_nnodes;
t->hfsp_extent_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC; t->hfsp_extent_file_start = hfsp_curblock;
t->curblock++; hfsp_curblock++;
iso_msg_debug(t->image->id, "(d) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes); iso_msg_debug(t->image->id, "(d) hfsp_curblock=%d, nodes =%d", hfsp_curblock, t->hfsp_nnodes);
link_blocks = 0; link_blocks = 0;
for (i = 0; i < t->hfsp_nleafs; i++) for (i = 0; i < t->hfsp_nleafs; i++)
if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK) if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK)
{ {
/* ts B20623 : was: t->hfsp_leafs[i].symlink_block = hfsp_curblock;
t->hfsp_leafs[i].symlink_block = t->curblock; hfsp_curblock += (t->hfsp_leafs[i].symlink_size + block_size - 1) / block_size;
t->curblock += (t->hfsp_leafs[i].symlink_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE;
*/
t->hfsp_leafs[i].symlink_block =
t->curblock * HFSPLUS_ISO_BLOCK_FAC + link_blocks;
link_blocks += (t->hfsp_leafs[i].symlink_size +
HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE;
} }
/* ts B20623 */ t->curblock = hfsp_curblock / block_fac;
t->curblock += link_blocks / HFSPLUS_ISO_BLOCK_FAC; if (hfsp_curblock % block_fac)
if (link_blocks % HFSPLUS_ISO_BLOCK_FAC)
t->curblock++; t->curblock++;
iso_msg_debug(t->image->id, "(a) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes); iso_msg_debug(t->image->id, "(a) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
@ -518,6 +575,7 @@ int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
static void set_time (uint32_t *tm, uint32_t t) static void set_time (uint32_t *tm, uint32_t t)
{ {
iso_msb ((uint8_t *) tm, t + 2082844800, 4); iso_msb ((uint8_t *) tm, t + 2082844800, 4);
@ -570,9 +628,12 @@ write_sb (Ecma119Image *t)
static char buffer[1024]; static char buffer[1024];
int ret; int ret;
int i; int i;
uint32_t block_size;
iso_msg_debug(t->image->id, "Write HFS+ superblock"); iso_msg_debug(t->image->id, "Write HFS+ superblock");
block_size = t->hfsp_block_size;
memset (buffer, 0, sizeof (buffer)); memset (buffer, 0, sizeof (buffer));
ret = iso_write(t, buffer, 1024); ret = iso_write(t, buffer, 1024);
if (ret < 0) if (ret < 0)
@ -592,28 +653,28 @@ write_sb (Ecma119Image *t)
set_time (&sb.fsck_time, t->now); set_time (&sb.fsck_time, t->now);
iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4); iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4);
iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4); iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4);
iso_msb ((uint8_t *) &sb.blksize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.blksize, block_size, 4);
iso_msb ((uint8_t *) &sb.catalog_node_id, t->hfsp_cat_id, 4); iso_msb ((uint8_t *) &sb.catalog_node_id, t->hfsp_cat_id, 4);
iso_msb ((uint8_t *) &sb.rsrc_clumpsize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.rsrc_clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.data_clumpsize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.data_clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.total_blocks, t->hfsp_total_blocks, 4); iso_msb ((uint8_t *) &sb.total_blocks, t->hfsp_total_blocks, 4);
iso_msb ((uint8_t *) &sb.encodings_bitmap + 4, 1, 4); iso_msb ((uint8_t *) &sb.encodings_bitmap + 4, 1, 4);
iso_msb ((uint8_t *) &sb.allocations_file.size + 4, t->hfsp_allocation_size, 4); iso_msb ((uint8_t *) &sb.allocations_file.size + 4, t->hfsp_allocation_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.extents[0].start, t->hfsp_allocation_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.allocations_file.extents[0].start, t->hfsp_allocation_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.size + 4, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.extents_file.size + 4, block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.clumpsize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &sb.extents_file.clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.blocks, 1, 4); iso_msb ((uint8_t *) &sb.extents_file.blocks, 1, 4);
iso_msb ((uint8_t *) &sb.extents_file.extents[0].start, t->hfsp_extent_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.extents_file.extents[0].start, t->hfsp_extent_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.extents_file.extents[0].count, 1, 4); iso_msb ((uint8_t *) &sb.extents_file.extents[0].count, 1, 4);
iso_msg_debug(t->image->id, "extent_file_start = %d\n", (int)t->hfsp_extent_file_start); iso_msg_debug(t->image->id, "extent_file_start = %d\n", (int)t->hfsp_extent_file_start);
iso_msb ((uint8_t *) &sb.catalog_file.size + 4, HFSPLUS_BLOCK_SIZE * 2 * t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &sb.catalog_file.size + 4, block_size * 2 * t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, HFSPLUS_BLOCK_SIZE * 2, 4); iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, block_size * 2, 4);
iso_msb ((uint8_t *) &sb.catalog_file.blocks, 2 * t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &sb.catalog_file.blocks, 2 * t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &sb.catalog_file.extents[0].start, t->hfsp_catalog_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.catalog_file.extents[0].start, t->hfsp_catalog_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.catalog_file.extents[0].count, 2 * t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &sb.catalog_file.extents[0].count, 2 * t->hfsp_nnodes, 4);
@ -625,8 +686,8 @@ write_sb (Ecma119Image *t)
t->hfsp_bless_id[i], 4); t->hfsp_bless_id[i], 4);
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u", iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u",
i, t->hfsp_bless_id[i]); i, t->hfsp_bless_id[i]);
#endif /* Libisofs_ts_debuG */ #endif /* Libisofs_ts_debuG */
} }
@ -642,18 +703,21 @@ static
int hfsplus_writer_write_data(IsoImageWriter *writer) int hfsplus_writer_write_data(IsoImageWriter *writer)
{ {
int ret; int ret;
static char buffer[2 * HFSPLUS_BLOCK_SIZE]; static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
Ecma119Image *t; Ecma119Image *t;
struct hfsplus_btnode *node_head; struct hfsplus_btnode *node_head;
struct hfsplus_btheader *tree_head; struct hfsplus_btheader *tree_head;
int level; int level;
uint32_t curpos = 1, i; uint32_t curpos = 1, i, block_fac, cat_node_size, block_size;
if (writer == NULL) { if (writer == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
t = writer->target; t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
cat_node_size = t->hfsp_cat_node_size;
iso_msg_debug(t->image->id, "(b) %d written", (int) t->bytes_written / 0x800); iso_msg_debug(t->image->id, "(b) %d written", (int) t->bytes_written / 0x800);
@ -675,27 +739,27 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
iso_msb ((uint8_t *) &tree_head->leaf_records, t->hfsp_nleafs, 4); iso_msb ((uint8_t *) &tree_head->leaf_records, t->hfsp_nleafs, 4);
iso_msb ((uint8_t *) &tree_head->first_leaf_node, t->hfsp_nnodes - t->hfsp_levels[0].level_size, 4); iso_msb ((uint8_t *) &tree_head->first_leaf_node, t->hfsp_nnodes - t->hfsp_levels[0].level_size, 4);
iso_msb ((uint8_t *) &tree_head->last_leaf_node, t->hfsp_nnodes - 1, 4); iso_msb ((uint8_t *) &tree_head->last_leaf_node, t->hfsp_nnodes - 1, 4);
iso_msb ((uint8_t *) &tree_head->nodesize, HFSPLUS_CAT_NODE_SIZE, 2); iso_msb ((uint8_t *) &tree_head->nodesize, cat_node_size, 2);
iso_msb ((uint8_t *) &tree_head->keysize, 6 + 2 * LIBISO_HFSPLUS_NAME_MAX, 2); iso_msb ((uint8_t *) &tree_head->keysize, 6 + 2 * LIBISO_HFSPLUS_NAME_MAX, 2);
iso_msb ((uint8_t *) &tree_head->total_nodes, t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &tree_head->total_nodes, t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4); iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, HFSPLUS_CAT_NODE_SIZE, 4); iso_msb ((uint8_t *) &tree_head->clump_size, cat_node_size, 4);
tree_head->key_compare = 0xcf; tree_head->key_compare = 0xcf;
iso_msb ((uint8_t *) &tree_head->attributes, 2 | 4, 4); iso_msb ((uint8_t *) &tree_head->attributes, 2 | 4, 4);
memset (buffer + 0xf8, -1, t->hfsp_nnodes / 8); memset (buffer + 0xf8, -1, t->hfsp_nnodes / 8);
buffer[0xf8 + (t->hfsp_nnodes / 8)] = 0xff00 >> (t->hfsp_nnodes % 8); buffer[0xf8 + (t->hfsp_nnodes / 8)] = 0xff00 >> (t->hfsp_nnodes % 8);
buffer[HFSPLUS_CAT_NODE_SIZE - 1] = sizeof (*node_head); buffer[cat_node_size - 1] = sizeof (*node_head);
buffer[HFSPLUS_CAT_NODE_SIZE - 3] = sizeof (*node_head) + sizeof (*tree_head); buffer[cat_node_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[HFSPLUS_CAT_NODE_SIZE - 5] = (char) 0xf8; buffer[cat_node_size - 5] = (char) 0xf8;
buffer[HFSPLUS_CAT_NODE_SIZE - 7] = (char) ((HFSPLUS_CAT_NODE_SIZE - 8) & 0xff); buffer[cat_node_size - 7] = (char) ((cat_node_size - 8) & 0xff);
buffer[HFSPLUS_CAT_NODE_SIZE - 8] = (HFSPLUS_CAT_NODE_SIZE - 8) >> 8; buffer[cat_node_size - 8] = (cat_node_size - 8) >> 8;
#ifdef Libisofs_hfsplus_verbose_debuG #ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n"); iso_msg_debug(t->image->id, "Write\n");
#endif #endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE); ret = iso_write(t, buffer, cat_node_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -720,7 +784,7 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff = sizeof (struct hfsplus_btnode); curoff = sizeof (struct hfsplus_btnode);
for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++) for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
{ {
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2); iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + curoff, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen + 6, 2); iso_msb ((uint8_t *) buffer + curoff, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen + 6, 2);
iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_levels[level - 1].nodes[curnode].parent_id, 4); iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_levels[level - 1].nodes[curnode].parent_id, 4);
@ -732,13 +796,13 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff += 4; curoff += 4;
curnode++; curnode++;
} }
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2); iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG #ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n"); iso_msg_debug(t->image->id, "Write\n");
#endif #endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE); ret = iso_write(t, buffer, cat_node_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -766,7 +830,7 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff = sizeof (struct hfsplus_btnode); curoff = sizeof (struct hfsplus_btnode);
for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++) for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
{ {
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2); iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG #ifdef Libisofs_hfsplus_verbose_debuG
@ -920,16 +984,16 @@ iso_msg_debug(t->image->id,
&blk, &sz); &blk, &sz);
if (ret <= 0) if (ret <= 0)
return ret; return ret;
blk *= HFSPLUS_ISO_BLOCK_FAC; blk *= block_fac;
} }
if (sz == 0) if (sz == 0)
blk = t->hfsp_part_start; blk = t->hfsp_part_start;
iso_msb ((uint8_t *) &data_fork->size, sz >> 32, 4); iso_msb ((uint8_t *) &data_fork->size, sz >> 32, 4);
iso_msb ((uint8_t *) &data_fork->size + 4, sz, 4); iso_msb ((uint8_t *) &data_fork->size + 4, sz, 4);
iso_msb ((uint8_t *) &data_fork->clumpsize, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &data_fork->clumpsize, block_size, 4);
iso_msb ((uint8_t *) &data_fork->blocks, (sz + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &data_fork->blocks, (sz + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &data_fork->extents[0].start, blk - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &data_fork->extents[0].start, blk - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + block_size - 1) / block_size, 4);
curoff += sizeof (*data_fork) * 2; curoff += sizeof (*data_fork) * 2;
/* FIXME: resource fork */ /* FIXME: resource fork */
@ -939,13 +1003,13 @@ iso_msg_debug(t->image->id,
} }
curnode++; curnode++;
} }
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2); iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG #ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n"); iso_msg_debug(t->image->id, "Write\n");
#endif #endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE); ret = iso_write(t, buffer, cat_node_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@ -953,38 +1017,30 @@ iso_msg_debug(t->image->id,
} }
memset (buffer, 0, sizeof (buffer)); memset (buffer, 0, sizeof (buffer));
ret = pad_up_block(t);
if (ret < 0)
return ret;
iso_msg_debug(t->image->id, "real extent_file_start = %d\n", (int)t->bytes_written / 2048); iso_msg_debug(t->image->id, "real extent_file_start = %d\n", (int)t->bytes_written / 2048);
node_head = (struct hfsplus_btnode *) buffer; node_head = (struct hfsplus_btnode *) buffer;
node_head->type = 1; node_head->type = 1;
iso_msb ((uint8_t *) &node_head->count, 3, 2); iso_msb ((uint8_t *) &node_head->count, 3, 2);
tree_head = (struct hfsplus_btheader *) (node_head + 1); tree_head = (struct hfsplus_btheader *) (node_head + 1);
iso_msb ((uint8_t *) &tree_head->nodesize, HFSPLUS_BLOCK_SIZE, 2); iso_msb ((uint8_t *) &tree_head->nodesize, block_size, 2);
iso_msb ((uint8_t *) &tree_head->keysize, 10, 2); iso_msb ((uint8_t *) &tree_head->keysize, 10, 2);
iso_msb ((uint8_t *) &tree_head->total_nodes, 1, 4); iso_msb ((uint8_t *) &tree_head->total_nodes, 1, 4);
iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4); iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, HFSPLUS_BLOCK_SIZE, 4); iso_msb ((uint8_t *) &tree_head->clump_size, block_size, 4);
iso_msb ((uint8_t *) &tree_head->attributes, 2, 4); iso_msb ((uint8_t *) &tree_head->attributes, 2, 4);
buffer[0xf8] = (char) 0x80; buffer[0xf8] = (char) 0x80;
buffer[HFSPLUS_BLOCK_SIZE - 1] = sizeof (*node_head); buffer[block_size - 1] = sizeof (*node_head);
buffer[HFSPLUS_BLOCK_SIZE - 3] = sizeof (*node_head) + sizeof (*tree_head); buffer[block_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[HFSPLUS_BLOCK_SIZE - 5] = (char) 0xf8; buffer[block_size - 5] = (char) 0xf8;
buffer[HFSPLUS_BLOCK_SIZE - 7] = (char) ((HFSPLUS_BLOCK_SIZE - 8) & 0xff); buffer[block_size - 7] = (char) ((block_size - 8) & 0xff);
buffer[HFSPLUS_BLOCK_SIZE - 8] = (HFSPLUS_BLOCK_SIZE - 8) >> 8; buffer[block_size - 8] = (block_size - 8) >> 8;
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE); ret = iso_write(t, buffer, block_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = pad_up_block(t);
if (ret < 0)
return ret;
iso_msg_debug(t->image->id, "(d) %d written", (int) t->bytes_written / 0x800); iso_msg_debug(t->image->id, "(d) %d written", (int) t->bytes_written / 0x800);
memset (buffer, 0, sizeof (buffer)); memset (buffer, 0, sizeof (buffer));
for (i = 0; i < t->hfsp_nleafs; i++) for (i = 0; i < t->hfsp_nleafs; i++)
@ -995,14 +1051,15 @@ iso_msg_debug(t->image->id,
ret = iso_write(t, sym->dest, t->hfsp_leafs[i].symlink_size); ret = iso_write(t, sym->dest, t->hfsp_leafs[i].symlink_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
overhead = t->hfsp_leafs[i].symlink_size % HFSPLUS_BLOCK_SIZE; overhead = t->hfsp_leafs[i].symlink_size % block_size;
if (overhead) if (overhead)
overhead = HFSPLUS_BLOCK_SIZE - overhead; overhead = block_size - overhead;
ret = iso_write(t, buffer, overhead); ret = iso_write(t, buffer, overhead);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
/* Need to align for start of next writer */
ret = pad_up_block(t); ret = pad_up_block(t);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1015,8 +1072,8 @@ static
int hfsplus_tail_writer_write_data(IsoImageWriter *writer) int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
{ {
int ret; int ret;
static char buffer[2 * HFSPLUS_BLOCK_SIZE]; static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
uint32_t complete_blocks, remaining_blocks; uint32_t complete_blocks, remaining_blocks, block_size;
int over; int over;
Ecma119Image *t; Ecma119Image *t;
@ -1025,28 +1082,29 @@ int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
} }
t = writer->target; t = writer->target;
block_size = t->hfsp_block_size;
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f", iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
(double) t->bytes_written); (double) t->bytes_written);
#endif #endif
memset (buffer, -1, sizeof (buffer)); memset (buffer, -1, sizeof (buffer));
complete_blocks = (t->hfsp_allocation_size - 1) / HFSPLUS_BLOCK_SIZE; complete_blocks = (t->hfsp_allocation_size - 1) / block_size;
remaining_blocks = t->hfsp_allocation_blocks - complete_blocks; remaining_blocks = t->hfsp_allocation_blocks - complete_blocks;
while (complete_blocks--) while (complete_blocks--)
{ {
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE); ret = iso_write(t, buffer, block_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
over = (t->hfsp_allocation_size - 1) % HFSPLUS_BLOCK_SIZE; over = (t->hfsp_allocation_size - 1) % block_size;
if (over) if (over)
{ {
memset (buffer + over, 0, sizeof (buffer) - over); memset (buffer + over, 0, sizeof (buffer) - over);
buffer[over] = 0xff00 >> (t->hfsp_total_blocks % 8); buffer[over] = 0xff00 >> (t->hfsp_total_blocks % 8);
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE); ret = iso_write(t, buffer, block_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
remaining_blocks--; remaining_blocks--;
@ -1055,29 +1113,32 @@ iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
/* When we have both FAT and HFS+ we may to overestimate needed blocks a bit. */ /* When we have both FAT and HFS+ we may to overestimate needed blocks a bit. */
while (remaining_blocks--) while (remaining_blocks--)
{ {
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE); ret = iso_write(t, buffer, block_size);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
#ifndef Libisofs_apm_flags_bit2
ret = pad_up_block(t); ret = pad_up_block(t);
if (ret < 0) if (ret < 0)
return ret; return ret;
#endif /* ! Libisofs_apm_flags_bit2 */
iso_msg_debug(t->image->id, "%d written", (int) t->bytes_written); iso_msg_debug(t->image->id, "%d written", (int) t->bytes_written);
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer writes sb at = %.f",
(double) t->bytes_written);
#endif
ret = write_sb (t); ret = write_sb (t);
#ifdef Libisofs_ts_debuG #ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f", iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f",
(double) t->bytes_written); (double) t->bytes_written);
#endif #endif
#ifdef Libisofs_apm_flags_bit2
ret = pad_up_block(t);
if (ret < 0)
return ret;
#endif /* Libisofs_apm_flags_bit2 */
return ret; return ret;
} }
@ -1117,6 +1178,7 @@ int hfsplus_writer_create(Ecma119Image *target)
IsoNode *pos; IsoNode *pos;
IsoDir *dir; IsoDir *dir;
int i; int i;
uint32_t cat_node_size;
writer = malloc(sizeof(IsoImageWriter)); writer = malloc(sizeof(IsoImageWriter));
if (writer == NULL) { if (writer == NULL) {
@ -1126,6 +1188,12 @@ int hfsplus_writer_create(Ecma119Image *target)
make_hfsplus_decompose_pages(); make_hfsplus_decompose_pages();
make_hfsplus_class_pages(); make_hfsplus_class_pages();
if (target->hfsp_block_size == 0)
target->hfsp_block_size = HFSPLUS_DEFAULT_BLOCK_SIZE;
target->hfsp_cat_node_size = 2 * target->hfsp_block_size;
target->hfsp_iso_block_fac = 2048 / target->hfsp_block_size;
cat_node_size = target->hfsp_cat_node_size;
writer->compute_data_blocks = hfsplus_writer_compute_data_blocks; writer->compute_data_blocks = hfsplus_writer_compute_data_blocks;
writer->write_vol_desc = nop_writer_write_vol_desc; writer->write_vol_desc = nop_writer_write_vol_desc;
writer->write_data = hfsplus_writer_write_data; writer->write_data = hfsplus_writer_write_data;
@ -1205,7 +1273,7 @@ int hfsplus_writer_create(Ecma119Image *target)
{ {
uint32_t last_start = 0; uint32_t last_start = 0;
uint32_t i; uint32_t i;
unsigned bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2; unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
target->hfsp_levels[level].nodes = malloc ((target->hfsp_nleafs + 1) * sizeof (target->hfsp_levels[level].nodes[0])); target->hfsp_levels[level].nodes = malloc ((target->hfsp_nleafs + 1) * sizeof (target->hfsp_levels[level].nodes[0]));
if (!target->hfsp_levels[level].nodes) if (!target->hfsp_levels[level].nodes)
@ -1231,7 +1299,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id;
target->hfsp_levels[level].level_size++; target->hfsp_levels[level].level_size++;
last_start = i; last_start = i;
bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2; bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
} }
bytes_rem -= target->hfsp_leafs[i].used_size; bytes_rem -= target->hfsp_leafs[i].used_size;
} }
@ -1258,7 +1326,7 @@ int hfsplus_writer_create(Ecma119Image *target)
uint32_t last_start = 0; uint32_t last_start = 0;
uint32_t i; uint32_t i;
uint32_t last_size; uint32_t last_size;
unsigned bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2; unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
last_size = target->hfsp_levels[level].level_size; last_size = target->hfsp_levels[level].level_size;
@ -1283,7 +1351,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id;
target->hfsp_levels[level].level_size++; target->hfsp_levels[level].level_size++;
last_start = i; last_start = i;
bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2; bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
} }
bytes_rem -= used_size; bytes_rem -= used_size;
} }
@ -1299,7 +1367,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_nlevels = level + 1; target->hfsp_nlevels = level + 1;
if (target->hfsp_nnodes > (HFSPLUS_CAT_NODE_SIZE - 0x100) * 8) if (target->hfsp_nnodes > (cat_node_size - 0x100) * 8)
{ {
return iso_msg_submit(target->image->id, ISO_MANGLE_TOO_MUCH_FILES, 0, return iso_msg_submit(target->image->id, ISO_MANGLE_TOO_MUCH_FILES, 0,
"HFS+ map nodes aren't implemented"); "HFS+ map nodes aren't implemented");

View File

@ -1467,6 +1467,27 @@ int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable);
int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts, int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts,
uint8_t serial_number[8]); uint8_t serial_number[8]);
/**
* Set the block size for Apple Partition Map and for HFS+.
*
* @param opts
* The option set to be manipulated.
* @param hfsp_block_size
* The allocation block size to be used by the HFS+ fileystem.
* 0, 512, or 2048
* @param hfsp_block_size
* The block size to be used for and within the Apple Partition Map.
* 0, 512, or 2048.
* Size 512 is not compatible with options which produce GPT.
* @return
* 1 success, < 0 error
*
* @since 1.2.4
*/
int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts,
int hfsp_block_size, int apm_block_size);
/** /**
* Whether to use newer ISO-9660:1999 version. * Whether to use newer ISO-9660:1999 version.
* *
@ -7343,6 +7364,11 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
(FAILURE, HIGH, -390) */ (FAILURE, HIGH, -390) */
#define ISO_BOOT_NO_EFI_ELTO 0xE830FE7A #define ISO_BOOT_NO_EFI_ELTO 0xE830FE7A
/** Not a supported HFS+ or APM block size (FAILURE, HIGH, -391) */
#define ISO_BOOT_HFSP_BAD_BSIZE 0xE830FE79
/** APM block size prevents coexistence with GPT (FAILURE, HIGH, -392) */
#define ISO_BOOT_APM_GPT_BSIZE 0xE830FE78
/* Internal developer note: /* Internal developer note:

View File

@ -289,6 +289,7 @@ iso_write_opts_set_efi_bootp;
iso_write_opts_set_fat; iso_write_opts_set_fat;
iso_write_opts_set_fifo_size; iso_write_opts_set_fifo_size;
iso_write_opts_set_hardlinks; iso_write_opts_set_hardlinks;
iso_write_opts_set_hfsp_block_size;
iso_write_opts_set_hfsp_serial_number; iso_write_opts_set_hfsp_serial_number;
iso_write_opts_set_hfsplus; iso_write_opts_set_hfsplus;
iso_write_opts_set_iso1999; iso_write_opts_set_iso1999;

View File

@ -490,6 +490,10 @@ const char *iso_error_to_msg(int errcode)
return "Attempt to use an MBR partition entry twice"; return "Attempt to use an MBR partition entry twice";
case ISO_BOOT_NO_EFI_ELTO: case ISO_BOOT_NO_EFI_ELTO:
return "No suitable El Torito EFI boot image for exposure as GPT partition"; return "No suitable El Torito EFI boot image for exposure as GPT partition";
case ISO_BOOT_HFSP_BAD_BSIZE:
return "Not a supported HFS+ or APM block size";
case ISO_BOOT_APM_GPT_BSIZE:
return "APM block size prevents coexistence with GPT";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -856,12 +856,11 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
uint32_t flags; uint32_t flags;
int block_fac; int block_fac;
if (flag & 1) if ((flag & 1) || (t->apm_req_flags & 4))
block_fac = 1; block_fac = 1;
else else
block_fac = 2048 / apm_block_size; block_fac = 2048 / apm_block_size;
memset(buf, apm_block_size, 0); memset(buf, apm_block_size, 0);
wpt = buf; wpt = buf;
@ -916,9 +915,12 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks) static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
{ {
int i, ret, gap_counter = 0, up_to; int i, ret, gap_counter = 0, up_to;
uint32_t part_end, goal; uint32_t part_end, goal, block_fac = 1;
char gap_name[33]; char gap_name[33];
if (t->apm_req_flags & 4)
block_fac = 2048 / t->apm_block_size;
/* Find out whether an entry with start_block <= 1 is requested */ /* Find out whether an entry with start_block <= 1 is requested */
for (i = 0; i < t->apm_req_count; i++) { for (i = 0; i < t->apm_req_count; i++) {
if (t->apm_req[i]->start_block <= 1) if (t->apm_req[i]->start_block <= 1)
@ -939,12 +941,12 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
if (i < up_to - 1) if (i < up_to - 1)
goal = t->apm_req[i]->start_block; goal = t->apm_req[i]->start_block;
else else
goal = img_blocks; goal = img_blocks * block_fac;
if (i == 1) { if (i == 1) {
/* Description of APM itself */ /* Description of APM itself */
/* Actual APM size is not yet known. Protection begins at PVD */ /* Actual APM size is not yet known. Protection begins at PVD */
part_end = 16; part_end = 16 * block_fac;
if (goal < 16 && goal> 1) if (goal < part_end && goal> 1)
part_end = goal; part_end = goal;
} else { } else {
part_end = t->apm_req[i - 1]->start_block + part_end = t->apm_req[i - 1]->start_block +
@ -983,45 +985,6 @@ static int rectify_apm(Ecma119Image *t)
{ {
int ret; int ret;
if (t->apm_req_count == 0)
return 1;
/* These are the only APM block sizes which can be processed here */
if (t->apm_block_size > 1536)
t->apm_block_size = 2048;
else if (t->apm_block_size > 768)
t->apm_block_size = 1024;
else
t->apm_block_size = 512;
if (t->gpt_req_count > 0 &&
t->apm_block_size != 2048 && t->apm_req_count > 0) {
t->apm_block_size = 2048;
iso_msgs_submit(0,
"GPT and APM requested. Had to force APM Block size to 2048.",
0, "DEBUG", 0);
}
if (t->apm_req_count > 0) {
ret = fill_apm_gaps(t, t->curblock);
if (ret < 0)
return ret;
}
return 1;
}
/* flag bit0= do not write Block0
*/
static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
int flag)
{
int i, ret;
/* This is a micro mick-up of an APM Block0
and also harmless x86 machine code.
*/
static uint8_t block0_template[8] = {
0x45, 0x52, 0x02, 0x00, 0xeb, 0x02, 0xff, 0xff
};
#ifdef NIX #ifdef NIX
/* Disabled */ /* Disabled */
@ -1042,6 +1005,42 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
} }
#endif /* NIX */ #endif /* NIX */
if (t->apm_req_count == 0)
return 1;
if (t->gpt_req_count > 0 &&
t->apm_block_size != 2048 && t->apm_req_count > 0) {
iso_msgs_submit(0,
"GPT and APM requested. APM block size would have to be 2048.",
0, "FAILURE", 0);
return ISO_BOOT_APM_GPT_BSIZE;
}
if (t->apm_req_count > 0) {
ret = fill_apm_gaps(t, t->curblock);
if (ret < 0)
return ret;
}
return 1;
}
/* flag bit0= do not write Block0
*/
static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
int flag)
{
int i, ret;
uint32_t block_fac = 1;
/* This is a micro mock-up of an APM Block0
and also harmless x86 machine code.
*/
static uint8_t block0_template[8] = {
0x45, 0x52, 0x02, 0x00, 0xeb, 0x02, 0xff, 0xff
};
if (t->apm_req_flags & 4)
block_fac = 2048 / t->apm_block_size;
if (t->apm_req_count <= 0) if (t->apm_req_count <= 0)
return 2; return 2;
@ -1051,7 +1050,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
number of APM partitions was determined. number of APM partitions was determined.
*/ */
t->apm_req[t->apm_req_count - 1]->block_count = t->apm_req[t->apm_req_count - 1]->block_count =
img_blocks - t->apm_req[t->apm_req_count - 1]->start_block; img_blocks * block_fac - t->apm_req[t->apm_req_count - 1]->start_block;
/* If it is still empty, remove it */ /* If it is still empty, remove it */
if(t->apm_req[t->apm_req_count - 1]->block_count == 0) { if(t->apm_req[t->apm_req_count - 1]->block_count == 0) {
free(t->apm_req[t->apm_req_count - 1]); free(t->apm_req[t->apm_req_count - 1]);

View File

@ -141,7 +141,7 @@ int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot);
*/ */
struct iso_apm_partition_request { struct iso_apm_partition_request {
/* Always given in blocks of 2 KiB. /* Given in blocks of 2 KiB unless (Ecma119Image.apm_req_flags & 4).
Written to the ISO image according to Ecma119Image.apm_block_size. Written to the ISO image according to Ecma119Image.apm_block_size.
*/ */
uint32_t start_block; uint32_t start_block;