New API call iso_write_opts_set_appended_as_gpt()

and marking of appended partitions in GPT if GPT emerges for other reasons.
This commit is contained in:
Thomas Schmitt 2015-02-06 11:59:25 +01:00
parent 0819f93f79
commit 527b613607
8 changed files with 418 additions and 46 deletions

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2013 Thomas Schmitt
* Copyright (c) 2009 - 2015 Thomas Schmitt
*
* 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
@ -1318,12 +1318,18 @@ ex:
static
int write_head_part1(Ecma119Image *target, int *write_count, int flag)
{
int res, i;
uint8_t *sa;
int res, i, ret;
uint8_t *sa, *sa_local = NULL;
IsoImageWriter *writer;
size_t buffer_size = 0, buffer_free = 0, buffer_start_free = 0;
sa = target->sys_area_as_written;
if (target->sys_area_already_written) {
LIBISO_ALLOC_MEM(sa_local, uint8_t, 16 * BLOCK_SIZE);
sa = sa_local;
} else {
sa = target->sys_area_as_written;
target->sys_area_already_written = 1;
}
iso_ring_buffer_get_buf_status(target->buffer, &buffer_size,
&buffer_start_free);
*write_count = 0;
@ -1360,9 +1366,16 @@ int write_head_part1(Ecma119Image *target, int *write_count, int flag)
*write_count = target->bytes_written / BLOCK_SIZE;
}
return ISO_SUCCESS;
ret = ISO_SUCCESS;
goto ex;
write_error:;
return res;
ret = res;
goto ex;
ex:
LIBISO_FREE_MEM(sa_local);
return ret;
}
static
@ -1483,6 +1496,10 @@ int iso_write_partition_file(Ecma119Image *target, char *path,
goto ex;
}
/* >>> need opportunity to read from input ISO image
resp. to just mark a partition in the older sessions
*/;
fp = fopen(path, "rb");
if (fp == NULL)
{ret = ISO_BAD_PARTITION_FILE; goto ex;}
@ -1528,8 +1545,10 @@ void issue_ucs2_warning_summary(size_t failures)
static
void *write_function(void *arg)
{
int res, first_partition = 1, last_partition = 0, sa_type;
int i;
int res, i;
#ifndef Libisofs_appended_partitions_inlinE
int first_partition = 1, last_partition = 0, sa_type;
#endif
IsoImageWriter *writer;
Ecma119Image *target = (Ecma119Image*)arg;
@ -1545,12 +1564,17 @@ void *write_function(void *arg)
/* write data for each writer */
for (i = 0; i < (int) target->nwriters; ++i) {
writer = target->writers[i];
if (target->gpt_backup_outside &&
writer->write_vol_desc == gpt_tail_writer_write_vol_desc)
continue;
res = writer->write_data(writer);
if (res < 0) {
goto write_error;
}
}
#ifndef Libisofs_appended_partitions_inlinE
/* Append partition data */
sa_type = (target->system_area_options >> 2) & 0x3f;
if (sa_type == 0) { /* MBR */
@ -1573,6 +1597,19 @@ void *write_function(void *arg)
goto write_error;
}
#endif /* ! Libisofs_appended_partitions_inlinE */
if (target->gpt_backup_outside) {
for (i = 0; i < (int) target->nwriters; ++i) {
writer = target->writers[i];
if (writer->write_vol_desc != gpt_tail_writer_write_vol_desc)
continue;
res = writer->write_data(writer);
if (res < 0)
goto write_error;
}
}
/* Transplant checksum buffer from Ecma119Image to IsoImage */
transplant_checksum_buffer(target, 0);
@ -1927,6 +1964,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
target->appended_part_prepad[i] = 0;
target->appended_part_start[i] = target->appended_part_size[i] = 0;
}
target->have_appended_partitions = 0;
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
target->hfsplus_blessed[i] = src->hfsplus_blessed[i];
if (target->hfsplus_blessed[i] != NULL)
@ -1946,6 +1984,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
target->gpt_req[i] = NULL;
target->gpt_req_count = 0;
target->gpt_req_flags = 0;
target->gpt_backup_outside = 0;
target->gpt_disk_guid_set = 0;
target->gpt_part_start = 0;
target->gpt_backup_end = 0;
@ -1953,11 +1992,23 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
target->gpt_max_entries = 0;
target->gpt_is_computed = 0;
target->sys_area_already_written = 0;
target->filesrc_start = 0;
target->filesrc_blocks = 0;
target->joliet_ucs2_failures = 0;
/* If partitions get appended, then the backup GPT cannot be part of
the ISO filesystem.
*/
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
if (target->opts->appended_partitions[i] != NULL) {
target->gpt_backup_outside = 1;
target->have_appended_partitions = 1;
break;
}
/*
* 2. Based on those options, create needed writers: iso, joliet...
* Each writer inits its structures and stores needed info into
@ -1991,6 +2042,13 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
if (opts->hfsplus || opts->fat) {
nwriters+= 2;
}
#ifdef Libisofs_appended_partitions_inlinE
nwriters++; /* Inline Partition Append Writer */
#endif
nwriters++; /* GPT backup tail writer */
nwriters++; /* Tail padding writer */
if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) {
@ -2139,6 +2197,14 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
#endif /* Libisofs_checksums_before_paddinG */
#ifdef Libisofs_appended_partitions_inlinE
ret = partappend_writer_create(target);
if (ret < 0)
goto target_cleanup;
#endif /* Libisofs_appended_partitions_inlinE */
#ifdef Libisofs_gpt_writer_lasT
/* This writer shall be the last one in the list, because it protects the
image on media which are seen as GPT partitioned.
@ -2204,6 +2270,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
for (i = 0; i < (int) target->nwriters; ++i) {
IsoImageWriter *writer = target->writers[i];
if (target->gpt_backup_outside &&
writer->write_vol_desc == gpt_tail_writer_write_vol_desc)
continue;
/* Exposing address of data start to IsoWriteOpts and memorizing
this address for all files which have no block address:
symbolic links, device files, empty data files.
@ -2220,6 +2290,14 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
if (ret < 0) {
goto target_cleanup;
}
#ifdef Libisofs_appended_partitions_inlinE
target->vol_space_size = target->curblock - opts->ms_block;
target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
#endif
}
ret = iso_patch_eltoritos(target);
@ -2231,6 +2309,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
goto target_cleanup;
}
#ifndef Libisofs_appended_partitions_inlinE
/*
* The volume space size is just the size of the last session, in
* case of ms images.
@ -2243,6 +2323,20 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
if (ret < 0)
goto target_cleanup;
#endif /* ! Libisofs_appended_partitions_inlinE */
if (target->gpt_backup_outside) {
for (i = 0; i < (int) target->nwriters; ++i) {
IsoImageWriter *writer = target->writers[i];
if (writer->write_vol_desc != gpt_tail_writer_write_vol_desc)
continue;
ret = writer->compute_data_blocks(writer);
if (ret < 0)
goto target_cleanup;
}
}
/* create the ring buffer */
if (opts->overwrite != NULL &&
opts->fifo_size < 32 + opts->partition_offset) {
@ -2732,6 +2826,7 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->efi_boot_partition = NULL;
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
wopts->appended_partitions[i] = NULL;
wopts->appended_as_gpt = 0;
wopts->ascii_disc_label[0] = 0;
wopts->will_cancel = 0;
wopts->allow_dir_id_ext = 0;
@ -3445,6 +3540,12 @@ int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
return ISO_SUCCESS;
}
int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt)
{
opts->appended_as_gpt = !!gpt;
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);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2013 Thomas Schmitt
* Copyright (c) 2009 - 2015 Thomas Schmitt
*
* 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
@ -480,6 +480,10 @@ struct iso_write_opts {
char *appended_partitions[ISO_MAX_PARTITIONS];
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
/* If 1: With appended partitions: create protective MBR and mark by GPT
*/
int appended_as_gpt;
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
*/
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
@ -756,6 +760,7 @@ struct ecma119_image
uint32_t appended_part_prepad[ISO_MAX_PARTITIONS];
uint32_t appended_part_start[ISO_MAX_PARTITIONS];
uint32_t appended_part_size[ISO_MAX_PARTITIONS];
int have_appended_partitions;
/* See IsoImage and libisofs.h */
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
@ -802,6 +807,9 @@ struct ecma119_image
/* bit0= GPT partitions may overlap */
int gpt_req_flags;
/* Whether the eventual backup GPT is not part of the ISO filesystem */
int gpt_backup_outside;
uint32_t efi_boot_part_size;
IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */
@ -822,6 +830,7 @@ struct ecma119_image
write_data() methods of the writers.
*/
uint8_t sys_area_as_written[16 * BLOCK_SIZE];
int sys_area_already_written;
/* Size of the filesrc_writer area (data file content).
This is available before any IsoImageWriter.compute_data_blocks()

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2014 Thomas Schmitt
* Copyright (c) 2009 - 2015 Thomas Schmitt
*
* 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
@ -4014,7 +4014,7 @@ int iso_analyze_gpt_backup(IsoImage *image, IsoDataSource *src, int flag)
if (sai->gpt_backup_lba >= ((uint64_t) sai->image_size) * 4 &&
(sai->mbr_req_count < 1 ||
sai->mbr_req[0]->start_block + sai->mbr_req[0]->block_count
!= sai->gpt_backup_lba + 1))
> sai->gpt_backup_lba + 1))
sprintf(comments + strlen(comments), "Implausible header LBA %.f, ",
(double) sai->gpt_backup_lba);
iso_block = sai->gpt_backup_lba / 4;
@ -4254,6 +4254,26 @@ int iso_analyze_gpt(IsoImage *image, IsoDataSource *src, int flag)
}
}
}
/* Check first GPT partition for ISO partition offset */
if (sai->partition_offset == 0 && sai->mbr_req_count > 0 &&
sai->gpt_req_count > 0) {
if (sai->mbr_req[0]->type_byte == 0xee &&
sai->mbr_req[0]->start_block == 1) { /* protective MBR */
start_block = sai->gpt_req[0]->start_block;
block_count = sai->gpt_req[0]->block_count;
if (start_block >= 64 && block_count >= 72 &&
start_block <= 2048 && start_block % 4 == 0 &&
block_count % 4 == 0 &&
(start_block + block_count) / 4 == sai->image_size) {
ret = iso_analyze_partition_offset(image, src, start_block, 0);
if (ret < 0)
return ret;
}
}
}
return 1;
}

View File

@ -4,7 +4,7 @@
/*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009-2014 Thomas Schmitt
* Copyright (c) 2009-2015 Thomas Schmitt
*
* 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
@ -2502,6 +2502,24 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
uint8_t partition_type, char *image_path, int flag);
/**
* Control whether partitions created by iso_write_opts_set_partition_img()
* are to be represented in MBR or as GPT partitions.
*
* @param opts
* The option set to be manipulated.
* @param gpt
* 0= represent as MBR partition; as GPT only if other GPT partitions
* are present
* 1= represent as GPT partition and cause protective MBR with a single
* partition which covers the whole output data.
* This may fail if other settings demand MBR partitions.
* @return
* ISO_SUCCESS or error
*
* @since 1.4.0
*/
int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt);
/**
* Inquire the start address of the file data blocks after having used
@ -3730,8 +3748,8 @@ int iso_image_get_system_area(IsoImage *img, char data[32768],
"If an MBR is detected, with at least one partition entry of non-zero size,", \
"then there may be:", \
" Partition offset : decimal", \
" if not 0 then a second ISO 9660 superblock was found to which MBR", \
" partition 1 is pointing.", \
" if not 0 then a second ISO 9660 superblock was found to which", \
" MBR partition 1 or GPT partition 1 is pointing.", \
" MBR heads per cyl : decimal", \
" conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \
" MBR secs per head : decimal", \

View File

@ -290,6 +290,7 @@ iso_write_opts_set_allow_longer_paths;
iso_write_opts_set_allow_lowercase;
iso_write_opts_set_always_gmt;
iso_write_opts_set_appendable;
iso_write_opts_set_appended_as_gpt;
iso_write_opts_set_default_dir_mode;
iso_write_opts_set_default_file_mode;
iso_write_opts_set_default_gid;

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2008 - 2015 Thomas Schmitt
* with special credits to H. Peter Anvin for isohybrid
* and to Matthew Garrett for isohybrid with GPT and APM
*
* 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
* or later as published by the Free Software Foundation.
* See COPYING file for details.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
@ -559,6 +569,7 @@ static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
/*
* @param flag bit0= make own random MBR Id from current time
* bit1= create protective MBR as of UEFI/GPT specs
*/
int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
int part_offset, int part_number, int fs_type,
@ -574,6 +585,11 @@ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
struct timeval tv;
struct timezone tz;
if (flag & 2) {
part_number = 1;
part_offset = 1;
}
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
boot_lba = t->bootsrc[0]->sections[0].block;
@ -639,14 +655,17 @@ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
wpt+= 16;
continue;
}
/* write byte 0x80
/* write byte 0x80 if bootable
write LBA_to_CHS(partition_offset)
write byte filesystem_type
write LBA_to_CHS(image_size-1)
write dword partition_offset
write dword image_size
*/
lsb_to_buf(&wpt, 0x80, 8, 0);
if (flag & 2)
lsb_to_buf(&wpt, 0x00, 8, 0);
else
lsb_to_buf(&wpt, 0x80, 8, 0);
lba512chs_to_buf(&wpt, part_offset, head_count, sector_count);
lsb_to_buf(&wpt, fs_type, 8, 0);
lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2008 Vreixo Formoso
* Copyright (c) 2010 - 2014 Thomas Schmitt
* Copyright (c) 2010 - 2015 Thomas Schmitt
*
* 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
@ -128,6 +128,7 @@ static uint32_t compute_partition_size(char *disk_path, uint32_t *size,
}
/* Compute size and position of appended partitions.
@param flag bit0= Partitions inside ISO : update t->curblock
*/
int iso_compute_append_partitions(Ecma119Image *t, int flag)
{
@ -170,6 +171,8 @@ int iso_compute_append_partitions(Ecma119Image *t, int flag)
t->appended_part_size[i] = size;
pos += add_pos + size;
t->total_size += (add_pos + size) * 2048;
if (flag & 1)
t->curblock = pos;
}
return ISO_SUCCESS;
}
@ -312,6 +315,7 @@ int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc,
/* @param flag bit0= zeroize partitions entries 2, 3, 4
bit0= UEFI protective MBR: start LBA = 1
*/
static
int iso_offset_partition_start(uint32_t img_blocks, uint32_t partition_offset,
@ -326,6 +330,11 @@ int iso_offset_partition_start(uint32_t img_blocks, uint32_t partition_offset,
&start_lba, &start_sec, &start_head, &start_cyl, 1);
iso_compute_cyl_head_sec((uint64_t) img_blocks, hpc, sph,
&end_lba, &end_sec, &end_head, &end_cyl, 0);
if (flag & 2) {
start_lba = 1;
start_sec = 2;
start_head = start_cyl = 0;
}
wpt = buf + 446;
/* Let pass only legal bootability values */
@ -1552,7 +1561,11 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
}
} else if (part_end < goal) {
memset(gpt_name, 0, 72);
sprintf((char *) gpt_name, "Gap%d", gap_counter);
if (goal == t->vol_space_size * (uint64_t) 4 &&
part_end == t->opts->partition_offset * (uint64_t) 4)
sprintf((char *) gpt_name, "ISO9660");
else
sprintf((char *) gpt_name, "Gap%d", gap_counter);
iso_ascii_utf_16le(gpt_name);
gap_counter++;
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
@ -1577,6 +1590,9 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
end_lba = req->start_block + req->block_count;
backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) *
4;
if (req->start_block == t->opts->partition_offset * ((uint64_t) 4) &&
req->block_count == ((uint64_t) 4) * 0xffffffff)
end_lba = t->vol_space_size * 4;
if (end_lba > backup_end_lba)
end_lba = backup_end_lba;
end_lba = end_lba - 1;
@ -1601,9 +1617,10 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
{
int ret, int_img_blocks, sa_type, i, will_append = 0, do_isohybrid = 0;
int first_partition = 1, last_partition = 4, apm_flag, part_type;
int gpt_count = 0, gpt_idx[128], apm_count = 0;
uint32_t img_blocks;
int first_partition = 1, last_partition = 4, apm_flag, part_type = 0;
int gpt_count = 0, gpt_idx[128], apm_count = 0, no_boot_mbr = 0;
int offset_flag = 0;
uint32_t img_blocks, gpt_blocks, mbrp1_blocks;
uint64_t blk;
uint8_t *wpt;
@ -1695,7 +1712,12 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
}
if (t->mbr_req_count > 0 && sa_type != 0)
return ISO_NON_MBR_SYS_AREA;
ret = iso_write_gpt(t, img_blocks, buf);
if (t->gpt_backup_outside)
gpt_blocks = t->total_size / 2048;
else
gpt_blocks = img_blocks;
ret = iso_write_gpt(t, gpt_blocks, buf);
if (ret < 0) {
iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT");
return ret;
@ -1724,12 +1746,19 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
else
part_type = 0x17;
if (t->opts->appended_as_gpt && t->have_appended_partitions) {
part_type = 0xee;
img_blocks = gpt_blocks;
no_boot_mbr = 2;
}
/* >>> ??? Why is partition_offset 0 here ?
It gets adjusted later by iso_offset_partition_start()
Would it harm to give the real offset here ?
*/;
ret = make_isolinux_mbr(&img_blocks, t, 0, 1, part_type, buf, 1);
ret = make_isolinux_mbr(&img_blocks, t, 0, 1, part_type, buf,
1 | no_boot_mbr);
if (ret != 1)
return ret;
} else if (sa_type == 1) {
@ -1773,9 +1802,17 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
With t->mbr_req_count > 0 this has already been done,
*/
img_blocks = t->curblock; /* value might be altered */
ret = iso_offset_partition_start(img_blocks, t->opts->partition_offset,
if (part_type == 0xee) {
mbrp1_blocks = t->total_size / 2048;
offset_flag |= 2 | 1; /* protective MBR, no other partitions */
} else {
mbrp1_blocks = img_blocks;
}
ret = iso_offset_partition_start(mbrp1_blocks,
t->opts->partition_offset,
t->partition_secs_per_head,
t->partition_heads_per_cyl, buf, 0);
t->partition_heads_per_cyl, buf,
offset_flag);
if (ret != ISO_SUCCESS) /* error should never happen */
return ISO_ASSERT_FAILURE;
}
@ -1783,27 +1820,29 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
/* This eventually overwrites the non-mbr_req partition table entries
made so far. Overwriting those from t->mbr_req is not allowed.
*/
for (i = first_partition - 1; i <= last_partition - 1; i++) {
if (t->opts->appended_partitions[i] == NULL)
continue;
if (i < t->mbr_req_count)
return ISO_BOOT_MBR_COLLISION;
if (sa_type == 3) {
ret = write_sun_partition_entry(i + 1,
if (sa_type == 3 || !t->opts->appended_as_gpt) {
for (i = first_partition - 1; i <= last_partition - 1; i++) {
if (t->opts->appended_partitions[i] == NULL)
continue;
if (i < t->mbr_req_count)
return ISO_BOOT_MBR_COLLISION;
if (sa_type == 3) {
ret = write_sun_partition_entry(i + 1,
t->opts->appended_partitions,
t->appended_part_start, t->appended_part_size,
ISO_SUN_CYL_SIZE,
buf, t->opts->appended_partitions[i][0] == 0);
} else {
ret = write_mbr_partition_entry(i + 1,
} else {
ret = write_mbr_partition_entry(i + 1,
t->opts->appended_part_types[i],
(uint64_t) t->appended_part_start[i],
(uint64_t) t->appended_part_size[i],
t->partition_secs_per_head, t->partition_heads_per_cyl,
buf, 0);
}
if (ret < 0)
return ret;
}
if (ret < 0)
return ret;
}
if (sa_type == 0 && (t->system_area_options & 0x4000) && !do_isohybrid) {
@ -1860,10 +1899,12 @@ int iso_align_isohybrid(Ecma119Image *t, int flag)
{ret = ISO_SUCCESS; goto ex;}
always_align = (t->system_area_options >> 8) & 3;
/* Take into account the backup GPT */;
ret = precompute_gpt(t);
if (ret < 0)
goto ex;
if (!t->gpt_backup_outside) {
/* Take into account the backup GPT */;
ret = precompute_gpt(t);
if (ret < 0)
goto ex;
}
img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size;
imgsize = ((off_t) img_blocks) * (off_t) 2048;
@ -2137,6 +2178,53 @@ fallback:;
}
int assess_appended_gpt(Ecma119Image *t, int flag)
{
static uint8_t basic_data_uuid[16] = {
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
};
static uint8_t efi_sys_uuid[16] = {
0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b
};
static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int i, ret;
uint8_t gpt_name[72], *type_uuid;
#ifndef Libisofs_appended_partitions_inlinE
if (!t->gpt_backup_outside)
return 2;
#endif
/* Represent in GPT only if other GPT partitions are already registered
or if appended partitions are explicitely desired for GPT-only.
*/
if (t->gpt_req_count == 0 &&
!(t->have_appended_partitions && t->opts->appended_as_gpt))
return 2;
/* Represent appended partitions */
for (i = 0; i <= 3; i++) {
if (t->opts->appended_partitions[i] == NULL)
continue;
memset(gpt_name, 0, 72);
sprintf((char *) gpt_name, "Appended%d", i + 1);
iso_ascii_utf_16le(gpt_name);
if (t->opts->appended_part_types[i] == 0xef)
type_uuid = efi_sys_uuid;
else
type_uuid = basic_data_uuid;
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
((uint64_t) t->appended_part_start[i]) * 4,
((uint64_t) t->appended_part_size[i]) * 4,
type_uuid, zero_uuid,
(uint64_t) 0, gpt_name);
if (ret < 0)
return ret;
}
return ISO_SUCCESS;
}
/* Probably already called by tail_writer_compute_data_blocks via
iso_align_isohybrid
@ -2181,6 +2269,9 @@ static int precompute_gpt(Ecma119Image *t)
if (ret < 0)
return ret;
/* Assess impact of appended partitions on GPT */
ret = assess_appended_gpt(t, 0);
#ifdef NIX
/* Disabled */
@ -2262,7 +2353,7 @@ static int precompute_gpt(Ecma119Image *t)
}
static int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *t;
int ret;
@ -2276,15 +2367,22 @@ static int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
if (ret < 0)
return ret;
}
t->curblock += t->gpt_backup_size;
/* The ISO block number after the backup GPT header */
t->gpt_backup_end = t->curblock;
if (t->gpt_backup_outside) {
t->total_size += t->gpt_backup_size * 2048;
/* The ISO block number after the backup GPT header */
t->gpt_backup_end = t->total_size / 2048;
} else {
t->curblock += t->gpt_backup_size;
/* The ISO block number after the backup GPT header */
t->gpt_backup_end = t->curblock;
}
return ISO_SUCCESS;
}
static int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer)
int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer)
{
return ISO_SUCCESS;
}
@ -2348,6 +2446,12 @@ tampered_head:;
free(backup_buf);
if (ret < 0)
return ret;
if (!t->gpt_backup_outside) {
/* >>> Why isn't t->curblock updated ? */;
}
return ISO_SUCCESS;
write_zeros:;
@ -2560,3 +2664,87 @@ int partprepend_writer_create(Ecma119Image *target)
}
#ifdef Libisofs_appended_partitions_inlinE
/* ----------------- Inline Partition Append Writer ------------------ */
static int partappend_writer_compute_data_blocks(IsoImageWriter *writer)
{
int ret;
ret = iso_compute_append_partitions(writer->target, 1);
return ret;
}
static int partappend_writer_write_vol_desc(IsoImageWriter *writer)
{
return ISO_SUCCESS;
}
static int partappend_writer_write_data(IsoImageWriter *writer)
{
Ecma119Image *target;
int res, first_partition = 1, last_partition = 0, sa_type;
int i;
target = writer->target;
/* Append partition data */
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->opts->appended_partitions[i] == NULL)
continue;
if (target->opts->appended_partitions[i][0] == 0)
continue;
res = iso_write_partition_file(target,
target->opts->appended_partitions[i],
target->appended_part_prepad[i],
target->appended_part_size[i], 0);
if (res < 0)
return res;
target->curblock += target->appended_part_size[i];
}
return ISO_SUCCESS;
}
static int partappend_writer_free_data(IsoImageWriter *writer)
{
return ISO_SUCCESS;
}
int partappend_writer_create(Ecma119Image *target)
{
IsoImageWriter *writer;
writer = calloc(1, sizeof(IsoImageWriter));
if (writer == NULL) {
return ISO_OUT_OF_MEM;
}
writer->compute_data_blocks = partappend_writer_compute_data_blocks;
writer->write_vol_desc = partappend_writer_write_vol_desc;
writer->write_data = partappend_writer_write_data;
writer->free_data = partappend_writer_free_data;
writer->data = NULL;
writer->target = target;
/* add this writer to image */
target->writers[target->nwriters++] = writer;
return ISO_SUCCESS;
}
#endif /* Libisofs_appended_partitions_inlinE */

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2008 Vreixo Formoso
* Copyright (c) 2012 Thomas Schmitt
* Copyright (c) 2012 - 2015 Thomas Schmitt
*
* 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
@ -281,10 +281,20 @@ struct iso_sun_disk_label_entry {
*/
int partprepend_writer_create(Ecma119Image *target);
/* Creates the Inline Partition Append Writer
*/
int partappend_writer_create(Ecma119Image *target);
/* Creates the GPT backup tail writer.
*/
int gpt_tail_writer_create(Ecma119Image *target);
/* Not for execution but only to identify the writer by
( writer->write_vol_desc == gpt_tail_writer_write_vol_desc )
*/
int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer);
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
void iso_ascii_utf_16le(uint8_t gap_name[72]);
@ -301,4 +311,10 @@ void iso_ascii_utf_16le(uint8_t gap_name[72]);
#define Libisofs_grub2_sparc_patch_adr_poS 0x228
#define Libisofs_grub2_sparc_patch_size_poS 0x230
/* >>> It is unclear whether there is a use case for appended partitions
inside the ISO filesystem range.
# define Libisofs_appended_partitions_inlinE yes
*/
#endif /* SYSTEM_AREA_H_ */