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 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -1318,12 +1318,18 @@ ex:
static static
int write_head_part1(Ecma119Image *target, int *write_count, int flag) int write_head_part1(Ecma119Image *target, int *write_count, int flag)
{ {
int res, i; int res, i, ret;
uint8_t *sa; uint8_t *sa, *sa_local = NULL;
IsoImageWriter *writer; IsoImageWriter *writer;
size_t buffer_size = 0, buffer_free = 0, buffer_start_free = 0; 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, iso_ring_buffer_get_buf_status(target->buffer, &buffer_size,
&buffer_start_free); &buffer_start_free);
*write_count = 0; *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; *write_count = target->bytes_written / BLOCK_SIZE;
} }
return ISO_SUCCESS; ret = ISO_SUCCESS;
goto ex;
write_error:; write_error:;
return res; ret = res;
goto ex;
ex:
LIBISO_FREE_MEM(sa_local);
return ret;
} }
static static
@ -1483,6 +1496,10 @@ int iso_write_partition_file(Ecma119Image *target, char *path,
goto ex; goto ex;
} }
/* >>> need opportunity to read from input ISO image
resp. to just mark a partition in the older sessions
*/;
fp = fopen(path, "rb"); fp = fopen(path, "rb");
if (fp == NULL) if (fp == NULL)
{ret = ISO_BAD_PARTITION_FILE; goto ex;} {ret = ISO_BAD_PARTITION_FILE; goto ex;}
@ -1528,8 +1545,10 @@ void issue_ucs2_warning_summary(size_t failures)
static static
void *write_function(void *arg) void *write_function(void *arg)
{ {
int res, first_partition = 1, last_partition = 0, sa_type; int res, i;
int i; #ifndef Libisofs_appended_partitions_inlinE
int first_partition = 1, last_partition = 0, sa_type;
#endif
IsoImageWriter *writer; IsoImageWriter *writer;
Ecma119Image *target = (Ecma119Image*)arg; Ecma119Image *target = (Ecma119Image*)arg;
@ -1545,12 +1564,17 @@ void *write_function(void *arg)
/* write data for each writer */ /* write data for each writer */
for (i = 0; i < (int) target->nwriters; ++i) { for (i = 0; i < (int) target->nwriters; ++i) {
writer = target->writers[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); res = writer->write_data(writer);
if (res < 0) { if (res < 0) {
goto write_error; goto write_error;
} }
} }
#ifndef Libisofs_appended_partitions_inlinE
/* Append partition data */ /* Append partition data */
sa_type = (target->system_area_options >> 2) & 0x3f; sa_type = (target->system_area_options >> 2) & 0x3f;
if (sa_type == 0) { /* MBR */ if (sa_type == 0) { /* MBR */
@ -1573,6 +1597,19 @@ void *write_function(void *arg)
goto write_error; 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 from Ecma119Image to IsoImage */
transplant_checksum_buffer(target, 0); 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_prepad[i] = 0;
target->appended_part_start[i] = target->appended_part_size[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++) { for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
target->hfsplus_blessed[i] = src->hfsplus_blessed[i]; target->hfsplus_blessed[i] = src->hfsplus_blessed[i];
if (target->hfsplus_blessed[i] != NULL) 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[i] = NULL;
target->gpt_req_count = 0; target->gpt_req_count = 0;
target->gpt_req_flags = 0; target->gpt_req_flags = 0;
target->gpt_backup_outside = 0;
target->gpt_disk_guid_set = 0; target->gpt_disk_guid_set = 0;
target->gpt_part_start = 0; target->gpt_part_start = 0;
target->gpt_backup_end = 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_max_entries = 0;
target->gpt_is_computed = 0; target->gpt_is_computed = 0;
target->sys_area_already_written = 0;
target->filesrc_start = 0; target->filesrc_start = 0;
target->filesrc_blocks = 0; target->filesrc_blocks = 0;
target->joliet_ucs2_failures = 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... * 2. Based on those options, create needed writers: iso, joliet...
* Each writer inits its structures and stores needed info into * 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) { if (opts->hfsplus || opts->fat) {
nwriters+= 2; nwriters+= 2;
} }
#ifdef Libisofs_appended_partitions_inlinE
nwriters++; /* Inline Partition Append Writer */
#endif
nwriters++; /* GPT backup tail writer */ nwriters++; /* GPT backup tail writer */
nwriters++; /* Tail padding writer */ nwriters++; /* Tail padding writer */
if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) { 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 */ #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 #ifdef Libisofs_gpt_writer_lasT
/* This writer shall be the last one in the list, because it protects the /* This writer shall be the last one in the list, because it protects the
image on media which are seen as GPT partitioned. 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) { for (i = 0; i < (int) target->nwriters; ++i) {
IsoImageWriter *writer = target->writers[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 /* Exposing address of data start to IsoWriteOpts and memorizing
this address for all files which have no block address: this address for all files which have no block address:
symbolic links, device files, empty data files. 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) { if (ret < 0) {
goto target_cleanup; 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); ret = iso_patch_eltoritos(target);
@ -2231,6 +2309,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
goto target_cleanup; goto target_cleanup;
} }
#ifndef Libisofs_appended_partitions_inlinE
/* /*
* The volume space size is just the size of the last session, in * The volume space size is just the size of the last session, in
* case of ms images. * case of ms images.
@ -2243,6 +2323,20 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
if (ret < 0) if (ret < 0)
goto target_cleanup; 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 */ /* create the ring buffer */
if (opts->overwrite != NULL && if (opts->overwrite != NULL &&
opts->fifo_size < 32 + opts->partition_offset) { 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; wopts->efi_boot_partition = NULL;
for (i = 0; i < ISO_MAX_PARTITIONS; i++) for (i = 0; i < ISO_MAX_PARTITIONS; i++)
wopts->appended_partitions[i] = NULL; wopts->appended_partitions[i] = NULL;
wopts->appended_as_gpt = 0;
wopts->ascii_disc_label[0] = 0; wopts->ascii_disc_label[0] = 0;
wopts->will_cancel = 0; wopts->will_cancel = 0;
wopts->allow_dir_id_ext = 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; 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) int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label)
{ {
strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1); strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -480,6 +480,10 @@ struct iso_write_opts {
char *appended_partitions[ISO_MAX_PARTITIONS]; char *appended_partitions[ISO_MAX_PARTITIONS];
uint8_t appended_part_types[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. /* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
*/ */
char ascii_disc_label[ISO_DISC_LABEL_SIZE]; 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_prepad[ISO_MAX_PARTITIONS];
uint32_t appended_part_start[ISO_MAX_PARTITIONS]; uint32_t appended_part_start[ISO_MAX_PARTITIONS];
uint32_t appended_part_size[ISO_MAX_PARTITIONS]; uint32_t appended_part_size[ISO_MAX_PARTITIONS];
int have_appended_partitions;
/* See IsoImage and libisofs.h */ /* See IsoImage and libisofs.h */
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]; IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
@ -802,6 +807,9 @@ struct ecma119_image
/* bit0= GPT partitions may overlap */ /* bit0= GPT partitions may overlap */
int gpt_req_flags; 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; uint32_t efi_boot_part_size;
IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */ IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */
@ -822,6 +830,7 @@ struct ecma119_image
write_data() methods of the writers. write_data() methods of the writers.
*/ */
uint8_t sys_area_as_written[16 * BLOCK_SIZE]; uint8_t sys_area_as_written[16 * BLOCK_SIZE];
int sys_area_already_written;
/* Size of the filesrc_writer area (data file content). /* Size of the filesrc_writer area (data file content).
This is available before any IsoImageWriter.compute_data_blocks() This is available before any IsoImageWriter.compute_data_blocks()

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -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 && if (sai->gpt_backup_lba >= ((uint64_t) sai->image_size) * 4 &&
(sai->mbr_req_count < 1 || (sai->mbr_req_count < 1 ||
sai->mbr_req[0]->start_block + sai->mbr_req[0]->block_count 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, ", sprintf(comments + strlen(comments), "Implausible header LBA %.f, ",
(double) sai->gpt_backup_lba); (double) sai->gpt_backup_lba);
iso_block = sai->gpt_backup_lba / 4; 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; return 1;
} }

View File

@ -4,7 +4,7 @@
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -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, int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
uint8_t partition_type, char *image_path, int flag); 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 * 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,", \ "If an MBR is detected, with at least one partition entry of non-zero size,", \
"then there may be:", \ "then there may be:", \
" Partition offset : decimal", \ " Partition offset : decimal", \
" if not 0 then a second ISO 9660 superblock was found to which MBR", \ " if not 0 then a second ISO 9660 superblock was found to which", \
" partition 1 is pointing.", \ " MBR partition 1 or GPT partition 1 is pointing.", \
" MBR heads per cyl : decimal", \ " MBR heads per cyl : decimal", \
" conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \ " conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \
" MBR secs per head : decimal", \ " 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_allow_lowercase;
iso_write_opts_set_always_gmt; iso_write_opts_set_always_gmt;
iso_write_opts_set_appendable; iso_write_opts_set_appendable;
iso_write_opts_set_appended_as_gpt;
iso_write_opts_set_default_dir_mode; iso_write_opts_set_default_dir_mode;
iso_write_opts_set_default_file_mode; iso_write_opts_set_default_file_mode;
iso_write_opts_set_default_gid; 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 #ifdef HAVE_CONFIG_H
#include "../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 * @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 make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
int part_offset, int part_number, int fs_type, 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 timeval tv;
struct timezone tz; struct timezone tz;
if (flag & 2) {
part_number = 1;
part_offset = 1;
}
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4; hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
boot_lba = t->bootsrc[0]->sections[0].block; boot_lba = t->bootsrc[0]->sections[0].block;
@ -639,14 +655,17 @@ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
wpt+= 16; wpt+= 16;
continue; continue;
} }
/* write byte 0x80 /* write byte 0x80 if bootable
write LBA_to_CHS(partition_offset) write LBA_to_CHS(partition_offset)
write byte filesystem_type write byte filesystem_type
write LBA_to_CHS(image_size-1) write LBA_to_CHS(image_size-1)
write dword partition_offset write dword partition_offset
write dword image_size 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); lba512chs_to_buf(&wpt, part_offset, head_count, sector_count);
lsb_to_buf(&wpt, fs_type, 8, 0); lsb_to_buf(&wpt, fs_type, 8, 0);
lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count); 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) 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -128,6 +128,7 @@ static uint32_t compute_partition_size(char *disk_path, uint32_t *size,
} }
/* Compute size and position of appended partitions. /* 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) 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; t->appended_part_size[i] = size;
pos += add_pos + size; pos += add_pos + size;
t->total_size += (add_pos + size) * 2048; t->total_size += (add_pos + size) * 2048;
if (flag & 1)
t->curblock = pos;
} }
return ISO_SUCCESS; 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 /* @param flag bit0= zeroize partitions entries 2, 3, 4
bit0= UEFI protective MBR: start LBA = 1
*/ */
static static
int iso_offset_partition_start(uint32_t img_blocks, uint32_t partition_offset, 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); &start_lba, &start_sec, &start_head, &start_cyl, 1);
iso_compute_cyl_head_sec((uint64_t) img_blocks, hpc, sph, iso_compute_cyl_head_sec((uint64_t) img_blocks, hpc, sph,
&end_lba, &end_sec, &end_head, &end_cyl, 0); &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; wpt = buf + 446;
/* Let pass only legal bootability values */ /* 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) { } else if (part_end < goal) {
memset(gpt_name, 0, 72); 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); iso_ascii_utf_16le(gpt_name);
gap_counter++; gap_counter++;
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), 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; end_lba = req->start_block + req->block_count;
backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) * backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) *
4; 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) if (end_lba > backup_end_lba)
end_lba = backup_end_lba; end_lba = backup_end_lba;
end_lba = end_lba - 1; 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 iso_write_system_area(Ecma119Image *t, uint8_t *buf)
{ {
int ret, int_img_blocks, sa_type, i, will_append = 0, do_isohybrid = 0; 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 first_partition = 1, last_partition = 4, apm_flag, part_type = 0;
int gpt_count = 0, gpt_idx[128], apm_count = 0; int gpt_count = 0, gpt_idx[128], apm_count = 0, no_boot_mbr = 0;
uint32_t img_blocks; int offset_flag = 0;
uint32_t img_blocks, gpt_blocks, mbrp1_blocks;
uint64_t blk; uint64_t blk;
uint8_t *wpt; 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) if (t->mbr_req_count > 0 && sa_type != 0)
return ISO_NON_MBR_SYS_AREA; 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) { if (ret < 0) {
iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT"); iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT");
return ret; return ret;
@ -1724,12 +1746,19 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
else else
part_type = 0x17; 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 ? /* >>> ??? Why is partition_offset 0 here ?
It gets adjusted later by iso_offset_partition_start() It gets adjusted later by iso_offset_partition_start()
Would it harm to give the real offset here ? 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) if (ret != 1)
return ret; return ret;
} else if (sa_type == 1) { } 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, With t->mbr_req_count > 0 this has already been done,
*/ */
img_blocks = t->curblock; /* value might be altered */ 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_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 */ if (ret != ISO_SUCCESS) /* error should never happen */
return ISO_ASSERT_FAILURE; 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 /* This eventually overwrites the non-mbr_req partition table entries
made so far. Overwriting those from t->mbr_req is not allowed. made so far. Overwriting those from t->mbr_req is not allowed.
*/ */
for (i = first_partition - 1; i <= last_partition - 1; i++) { if (sa_type == 3 || !t->opts->appended_as_gpt) {
if (t->opts->appended_partitions[i] == NULL) for (i = first_partition - 1; i <= last_partition - 1; i++) {
continue; if (t->opts->appended_partitions[i] == NULL)
if (i < t->mbr_req_count) continue;
return ISO_BOOT_MBR_COLLISION; if (i < t->mbr_req_count)
if (sa_type == 3) { return ISO_BOOT_MBR_COLLISION;
ret = write_sun_partition_entry(i + 1, if (sa_type == 3) {
ret = write_sun_partition_entry(i + 1,
t->opts->appended_partitions, t->opts->appended_partitions,
t->appended_part_start, t->appended_part_size, t->appended_part_start, t->appended_part_size,
ISO_SUN_CYL_SIZE, ISO_SUN_CYL_SIZE,
buf, t->opts->appended_partitions[i][0] == 0); buf, t->opts->appended_partitions[i][0] == 0);
} else { } else {
ret = write_mbr_partition_entry(i + 1, ret = write_mbr_partition_entry(i + 1,
t->opts->appended_part_types[i], t->opts->appended_part_types[i],
(uint64_t) t->appended_part_start[i], (uint64_t) t->appended_part_start[i],
(uint64_t) t->appended_part_size[i], (uint64_t) t->appended_part_size[i],
t->partition_secs_per_head, t->partition_heads_per_cyl, t->partition_secs_per_head, t->partition_heads_per_cyl,
buf, 0); buf, 0);
}
if (ret < 0)
return ret;
} }
if (ret < 0)
return ret;
} }
if (sa_type == 0 && (t->system_area_options & 0x4000) && !do_isohybrid) { 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;} {ret = ISO_SUCCESS; goto ex;}
always_align = (t->system_area_options >> 8) & 3; always_align = (t->system_area_options >> 8) & 3;
/* Take into account the backup GPT */; if (!t->gpt_backup_outside) {
ret = precompute_gpt(t); /* Take into account the backup GPT */;
if (ret < 0) ret = precompute_gpt(t);
goto ex; if (ret < 0)
goto ex;
}
img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size; img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size;
imgsize = ((off_t) img_blocks) * (off_t) 2048; 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 /* Probably already called by tail_writer_compute_data_blocks via
iso_align_isohybrid iso_align_isohybrid
@ -2181,6 +2269,9 @@ static int precompute_gpt(Ecma119Image *t)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Assess impact of appended partitions on GPT */
ret = assess_appended_gpt(t, 0);
#ifdef NIX #ifdef NIX
/* Disabled */ /* 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; Ecma119Image *t;
int ret; int ret;
@ -2276,15 +2367,22 @@ static int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
t->curblock += t->gpt_backup_size;
/* The ISO block number after the backup GPT header */ if (t->gpt_backup_outside) {
t->gpt_backup_end = t->curblock; 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; 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; return ISO_SUCCESS;
} }
@ -2348,6 +2446,12 @@ tampered_head:;
free(backup_buf); free(backup_buf);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!t->gpt_backup_outside) {
/* >>> Why isn't t->curblock updated ? */;
}
return ISO_SUCCESS; return ISO_SUCCESS;
write_zeros:; 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) 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -281,10 +281,20 @@ struct iso_sun_disk_label_entry {
*/ */
int partprepend_writer_create(Ecma119Image *target); int partprepend_writer_create(Ecma119Image *target);
/* Creates the Inline Partition Append Writer
*/
int partappend_writer_create(Ecma119Image *target);
/* Creates the GPT backup tail writer. /* Creates the GPT backup tail writer.
*/ */
int gpt_tail_writer_create(Ecma119Image *target); 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 */ /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
void iso_ascii_utf_16le(uint8_t gap_name[72]); 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_adr_poS 0x228
#define Libisofs_grub2_sparc_patch_size_poS 0x230 #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_ */ #endif /* SYSTEM_AREA_H_ */