First stage of implementation of GPT production.
The writer class for the backup GPT is not implemented yet.
This commit is contained in:
parent
714ef6493a
commit
bcd4b88319
@ -125,6 +125,9 @@ void ecma119_image_free(Ecma119Image *t)
|
|||||||
for (i = 0; (int) i < t->apm_req_count; i++)
|
for (i = 0; (int) i < t->apm_req_count; i++)
|
||||||
if (t->apm_req[i] != NULL)
|
if (t->apm_req[i] != NULL)
|
||||||
free(t->apm_req[i]);
|
free(t->apm_req[i]);
|
||||||
|
for (i = 0; (int) i < t->gpt_req_count; i++)
|
||||||
|
if (t->gpt_req[i] != NULL)
|
||||||
|
free(t->gpt_req[i]);
|
||||||
|
|
||||||
free(t);
|
free(t);
|
||||||
}
|
}
|
||||||
@ -1881,13 +1884,15 @@ 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;
|
/* Note: Set apm_block_size to 2048, if desired, before pthread_create()
|
||||||
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
|
|
||||||
target->apm_req[i] = NULL;
|
|
||||||
/* Set apm_block_size to 2048, if desired, before pthread_create()
|
|
||||||
at the end of this function.
|
at the end of this function.
|
||||||
Register any Apple Partition Map entries before pthread_create().
|
Register any Apple Partition Map entries before pthread_create().
|
||||||
*/
|
*/
|
||||||
|
target->apm_block_size = 512;
|
||||||
|
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
|
||||||
|
target->apm_req[i] = NULL;
|
||||||
|
for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
|
||||||
|
target->gpt_req[i] = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2. Based on those options, create needed writers: iso, joliet...
|
* 2. Based on those options, create needed writers: iso, joliet...
|
||||||
|
@ -70,10 +70,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* The maximum number of Apple Partition Map entries.
|
/* The theoretical maximum number of Apple Partition Map entries in the
|
||||||
|
System Area of an ISO image:
|
||||||
|
Block0 plus 63 entries with block size 512
|
||||||
*/
|
*/
|
||||||
#define ISO_APM_ENTRIES_MAX 63
|
#define ISO_APM_ENTRIES_MAX 63
|
||||||
|
|
||||||
|
/* The theoretical maximum number of GPT entries in the System Area of an
|
||||||
|
ISO image:
|
||||||
|
MBR plus GPT header block plus 248 GPT entries of 128 bytes each.
|
||||||
|
*/
|
||||||
|
#define ISO_GPT_ENTRIES_MAX 248
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the options for the image generation.
|
* Holds the options for the image generation.
|
||||||
@ -803,6 +811,12 @@ struct ecma119_image
|
|||||||
/* 512 by default. May be changed to 2048 before writer thread starts. */
|
/* 512 by default. May be changed to 2048 before writer thread starts. */
|
||||||
int apm_block_size;
|
int apm_block_size;
|
||||||
|
|
||||||
|
/* GPT description. To be composed during IsoImageWriter
|
||||||
|
method ->compute_data_blocks() by calling iso_register_gpt_entry().
|
||||||
|
*/
|
||||||
|
struct iso_gpt_partition_request *gpt_req[ISO_GPT_ENTRIES_MAX];
|
||||||
|
int gpt_req_count;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BP(a,b) [(b) - (a) + 1]
|
#define BP(a,b) [(b) - (a) + 1]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
* Copyright (c) 2009 Thomas Schmitt
|
* Copyright (c) 2009 - 2012 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
|
||||||
|
@ -7209,6 +7209,12 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
|
|||||||
/** Overlapping Apple Partition Map entries requested (FAILURE, HIGH, -384) */
|
/** Overlapping Apple Partition Map entries requested (FAILURE, HIGH, -384) */
|
||||||
#define ISO_BOOT_APM_OVERLAP 0xE830FE80
|
#define ISO_BOOT_APM_OVERLAP 0xE830FE80
|
||||||
|
|
||||||
|
/** Too many GPT entries requested (FAILURE, HIGH, -385) */
|
||||||
|
#define ISO_BOOT_TOO_MANY_GPT 0xE830FE7F
|
||||||
|
|
||||||
|
/** Overlapping GPT entries requested (FAILURE, HIGH, -386) */
|
||||||
|
#define ISO_BOOT_GPT_OVERLAP 0xE830FE7E
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal developer note:
|
/* Internal developer note:
|
||||||
|
@ -480,23 +480,7 @@ static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_gpt_entry(Ecma119Image *t, char *buf, uint8_t type_guid[16],
|
#ifdef NIX
|
||||||
off_t start_lba, off_t end_lba, uint8_t flags[8],
|
|
||||||
uint8_t name[72])
|
|
||||||
{
|
|
||||||
char *wpt = buf;
|
|
||||||
|
|
||||||
memcpy(wpt, type_guid, 16);
|
|
||||||
wpt += 16;
|
|
||||||
iso_random_uuid(t, (uint8_t *) wpt);
|
|
||||||
wpt += 16;
|
|
||||||
lsb_to_buf(&wpt, start_lba & 0xffffffff, 32, 0);
|
|
||||||
lsb_to_buf(&wpt, (start_lba >> 32) & 0xffffffff, 32, 0);
|
|
||||||
lsb_to_buf(&wpt, end_lba & 0xffffffff, 32, 0);
|
|
||||||
lsb_to_buf(&wpt, (end_lba >> 32) & 0xffffffff, 32, 0);
|
|
||||||
memcpy(wpt, name, 72);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
|
static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
|
||||||
{
|
{
|
||||||
@ -515,6 +499,9 @@ static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
|
|||||||
/* >>> First entry describes overall image , basic_data_uuid
|
/* >>> First entry describes overall image , basic_data_uuid
|
||||||
start_lba = ;
|
start_lba = ;
|
||||||
end_lba = ;
|
end_lba = ;
|
||||||
|
|
||||||
|
>>> replace write_gpt_entry by iso_quick_gpt_entry
|
||||||
|
|
||||||
write_gpt_entry(t, buf + 512 * part_start, basic_data_uuid,
|
write_gpt_entry(t, buf + 512 * part_start, basic_data_uuid,
|
||||||
off_t start_lba, off_t end_lba, uint8_t flags[8],
|
off_t start_lba, off_t end_lba, uint8_t flags[8],
|
||||||
uint8_t name[72])
|
uint8_t name[72])
|
||||||
@ -530,7 +517,7 @@ static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* >>> */;
|
/* >>> iso_quick_gpt_entry() */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,82 +526,7 @@ static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* NIX */
|
||||||
static int write_gpt_header_block(Ecma119Image *t, char *buf,
|
|
||||||
uint32_t part_start, uint32_t p_arr_crc)
|
|
||||||
{
|
|
||||||
static char *sig = "EFI PART";
|
|
||||||
static char revision[4] = {0x00, 0x00, 0x01, 0x00};
|
|
||||||
char *wpt;
|
|
||||||
uint32_t crc;
|
|
||||||
off_t back_lba;
|
|
||||||
|
|
||||||
memset(buf, 0, 512);
|
|
||||||
wpt = buf;
|
|
||||||
|
|
||||||
memcpy(wpt, sig, 8); /* no trailing 0 */
|
|
||||||
wpt += 8;
|
|
||||||
memcpy(wpt, revision, 4);
|
|
||||||
wpt += 4;
|
|
||||||
lsb_to_buf(&wpt, 92, 32, 0);
|
|
||||||
|
|
||||||
/* CRC will be inserted later */
|
|
||||||
wpt += 4;
|
|
||||||
|
|
||||||
/* reserved */
|
|
||||||
lsb_to_buf(&wpt, 0, 32, 0);
|
|
||||||
/* Own LBA low 32 */
|
|
||||||
lsb_to_buf(&wpt, 1, 32, 0);
|
|
||||||
/* Own LBA high 32 */
|
|
||||||
lsb_to_buf(&wpt, 0, 32, 0);
|
|
||||||
|
|
||||||
/* Backup LBA is 1 hd block before image end */
|
|
||||||
back_lba = t->curblock * 4 - 1;
|
|
||||||
lsb_to_buf(&wpt, (uint32_t) (back_lba & 0xffffffff), 32, 1);
|
|
||||||
lsb_to_buf(&wpt, (uint32_t) (back_lba >> 32), 32, 1);
|
|
||||||
|
|
||||||
/* First usable LBA for partitions (entry array occupies 32 hd blocks) */
|
|
||||||
lsb_to_buf(&wpt, part_start + 32, 32, 0);
|
|
||||||
lsb_to_buf(&wpt, 0, 32, 0);
|
|
||||||
|
|
||||||
/* Last usable LBA for partitions */
|
|
||||||
lsb_to_buf(&wpt, (uint32_t) ((back_lba - 32) & 0xffffffff), 32, 1);
|
|
||||||
lsb_to_buf(&wpt, (uint32_t) ((back_lba - 32) >> 32), 32, 1);
|
|
||||||
|
|
||||||
/* Disk GUID */
|
|
||||||
iso_random_uuid(t, (uint8_t *) wpt);
|
|
||||||
wpt += 16;
|
|
||||||
|
|
||||||
/* Partition entries start */
|
|
||||||
lsb_to_buf(&wpt, part_start, 32, 0);
|
|
||||||
lsb_to_buf(&wpt, 0, 32, 0);
|
|
||||||
|
|
||||||
/* Number of partition entries */
|
|
||||||
lsb_to_buf(&wpt, 128, 32, 0);
|
|
||||||
|
|
||||||
/* Size of a partition entry */
|
|
||||||
lsb_to_buf(&wpt, 128, 32, 0);
|
|
||||||
|
|
||||||
/* CRC-32 of the partition array */
|
|
||||||
lsb_to_buf(&wpt, p_arr_crc, 32, 0);
|
|
||||||
|
|
||||||
|
|
||||||
/* <<< Only for a first test */
|
|
||||||
if (wpt - buf != 92) {
|
|
||||||
iso_msgs_submit(0,
|
|
||||||
"program error : write_gpt_header_block : wpt != 92",
|
|
||||||
0, "FATAL", 0);
|
|
||||||
return ISO_ISOLINUX_CANT_PATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* CRC-32 of this header while head_crc is 0 */
|
|
||||||
wpt = buf + 16;
|
|
||||||
crc = iso_crc32_gpt((unsigned char *) buf, wpt - buf, 0);
|
|
||||||
lsb_to_buf(&wpt, crc, 32, 0);
|
|
||||||
|
|
||||||
return ISO_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -627,7 +539,7 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
|||||||
uint32_t id, part, nominal_part_size;
|
uint32_t id, part, nominal_part_size;
|
||||||
off_t hd_img_blocks, hd_boot_lba;
|
off_t hd_img_blocks, hd_boot_lba;
|
||||||
char *wpt;
|
char *wpt;
|
||||||
uint32_t boot_lba, mbr_id, p_arr_crc, part_start;
|
uint32_t boot_lba, mbr_id, p_arr_crc, part_start, max_gpt_entries;
|
||||||
int head_count, sector_count, ret;
|
int head_count, sector_count, ret;
|
||||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
|
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
|
||||||
/* For generating a weak random number */
|
/* For generating a weak random number */
|
||||||
@ -729,8 +641,11 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
|||||||
/* >>> ISOHYBRID : write primary GPT and compute p_arr_crc */;
|
/* >>> ISOHYBRID : write primary GPT and compute p_arr_crc */;
|
||||||
part_start = 4 + (apm_count + 1) * 4;
|
part_start = 4 + (apm_count + 1) * 4;
|
||||||
|
|
||||||
|
/* >>> compute max_gpt_entries from number of APM */
|
||||||
|
max_gpt_entries = 128; /* suffices for 6 payload APM entries */
|
||||||
|
|
||||||
ret = write_gpt_header_block(t, (char *) buf + 512,
|
ret = iso_write_gpt_header_block(t, (uint32_t) *img_blocks,
|
||||||
|
buf + 512, max_gpt_entries,
|
||||||
part_start, p_arr_crc);
|
part_start, p_arr_crc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -478,6 +478,10 @@ const char *iso_error_to_msg(int errcode)
|
|||||||
return "Too many Apple Partition Map entries requested";
|
return "Too many Apple Partition Map entries requested";
|
||||||
case ISO_BOOT_APM_OVERLAP:
|
case ISO_BOOT_APM_OVERLAP:
|
||||||
return "Overlapping Apple Partition Map entries requested";
|
return "Overlapping Apple Partition Map entries requested";
|
||||||
|
case ISO_BOOT_TOO_MANY_GPT:
|
||||||
|
return "Too many GPT entries requested";
|
||||||
|
case ISO_BOOT_GPT_OVERLAP:
|
||||||
|
return "Overlapping GPT entries requested";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
@ -723,16 +723,45 @@ int iso_quick_apm_entry(Ecma119Image *t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convenience frontend for iso_register_gpt_entry().
|
||||||
|
name has to be already encoded as UTF-16LE.
|
||||||
|
*/
|
||||||
|
int iso_quick_gpt_entry(Ecma119Image *t,
|
||||||
|
uint32_t start_block, uint32_t block_count,
|
||||||
|
uint8_t type_guid[16], uint8_t partition_guid[16],
|
||||||
|
uint64_t flags, uint8_t name[72])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct iso_gpt_partition_request *entry;
|
||||||
|
|
||||||
|
entry = calloc(1, sizeof(struct iso_gpt_partition_request));
|
||||||
|
if (entry == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
entry->start_block = start_block;
|
||||||
|
entry->block_count = block_count;
|
||||||
|
memcpy(entry->type_guid, type_guid, 16);
|
||||||
|
memcpy(entry->partition_guid, partition_guid, 16);
|
||||||
|
entry->flags = flags;
|
||||||
|
memcpy(entry->name, name, 72);
|
||||||
|
ret = iso_register_gpt_entry(t, entry, 0);
|
||||||
|
free(entry);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare the start_sectors of two iso_apm_partition_request
|
* Compare the start_sectors of two iso_apm_partition_request
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int cmp_apm_partition_request(const void *f1, const void *f2)
|
int cmp_partition_request(const void *f1, const void *f2)
|
||||||
{
|
{
|
||||||
struct iso_apm_partition_request *r1, *r2;
|
struct iso_partition_request {
|
||||||
|
uint32_t start_block;
|
||||||
|
uint32_t block_count;
|
||||||
|
} *r1, *r2;
|
||||||
|
|
||||||
r1 = *((struct iso_apm_partition_request **) f1);
|
r1 = *((struct iso_partition_request **) f1);
|
||||||
r2 = *((struct iso_apm_partition_request **) f2);
|
r2 = *((struct iso_partition_request **) f2);
|
||||||
if (r1->start_block < r2->start_block)
|
if (r1->start_block < r2->start_block)
|
||||||
return -1;
|
return -1;
|
||||||
if (r1->start_block > r2->start_block)
|
if (r1->start_block > r2->start_block)
|
||||||
@ -740,6 +769,7 @@ int cmp_apm_partition_request(const void *f1, const void *f2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* @param flag bit0= This is the entry in block 1. Its blocks are already in
|
/* @param flag bit0= This is the entry in block 1. Its blocks are already in
|
||||||
the desired apm_block_size unit. Set block_fac to 1.
|
the desired apm_block_size unit. Set block_fac to 1.
|
||||||
*/
|
*/
|
||||||
@ -842,7 +872,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
|||||||
|
|
||||||
/* Sort and fill gaps */
|
/* Sort and fill gaps */
|
||||||
qsort(t->apm_req, t->apm_req_count,
|
qsort(t->apm_req, t->apm_req_count,
|
||||||
sizeof(struct iso_apm_partition_request *), cmp_apm_partition_request);
|
sizeof(struct iso_apm_partition_request *), cmp_partition_request);
|
||||||
/* t->apm_req_count will grow during the loop */
|
/* t->apm_req_count will grow during the loop */
|
||||||
up_to = t->apm_req_count + 1;
|
up_to = t->apm_req_count + 1;
|
||||||
for (i = 1; i < up_to; i++) {
|
for (i = 1; i < up_to; i++) {
|
||||||
@ -862,7 +892,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
|||||||
}
|
}
|
||||||
if (part_end > goal) {
|
if (part_end > goal) {
|
||||||
iso_msg_submit(t->image->id, ISO_BOOT_APM_OVERLAP, 0,
|
iso_msg_submit(t->image->id, ISO_BOOT_APM_OVERLAP, 0,
|
||||||
"Program error: APM partitions %d and %d oberlap by %lu blocks",
|
"Program error: APM partitions %d and %d overlap by %lu blocks",
|
||||||
i - 1, i, part_end - goal);
|
i - 1, i, part_end - goal);
|
||||||
return ISO_BOOT_APM_OVERLAP;
|
return ISO_BOOT_APM_OVERLAP;
|
||||||
}
|
}
|
||||||
@ -878,7 +908,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
|||||||
|
|
||||||
/* Merge list of gap partitions with list of already sorted entries */
|
/* Merge list of gap partitions with list of already sorted entries */
|
||||||
qsort(t->apm_req, t->apm_req_count,
|
qsort(t->apm_req, t->apm_req_count,
|
||||||
sizeof(struct iso_apm_partition_request *), cmp_apm_partition_request);
|
sizeof(struct iso_apm_partition_request *), cmp_partition_request);
|
||||||
|
|
||||||
/* These are the only APM block sizes which can be processed here */
|
/* These are the only APM block sizes which can be processed here */
|
||||||
if (t->apm_block_size > 1536)
|
if (t->apm_block_size > 1536)
|
||||||
@ -914,11 +944,266 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void iso_write_gpt_entry(Ecma119Image *t, uint8_t *buf,
|
||||||
|
uint8_t type_guid[16], uint8_t part_uuid[16],
|
||||||
|
uint64_t start_lba, uint64_t end_lba,
|
||||||
|
uint64_t flags, uint8_t name[72])
|
||||||
|
{
|
||||||
|
char *wpt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wpt = (char *) buf;
|
||||||
|
memcpy(wpt, type_guid, 16);
|
||||||
|
wpt += 16;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (part_uuid[i])
|
||||||
|
break;
|
||||||
|
if (i < 16) {
|
||||||
|
memcpy(wpt, part_uuid, 16);
|
||||||
|
} else {
|
||||||
|
iso_random_uuid(t, (uint8_t *) wpt);
|
||||||
|
}
|
||||||
|
wpt += 16;
|
||||||
|
iso_lsb_to_buf(&wpt, start_lba & 0xffffffff, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, (start_lba >> 32) & 0xffffffff, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, end_lba & 0xffffffff, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, (end_lba >> 32) & 0xffffffff, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, flags & 0xffffffff, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, (flags >> 32) & 0xffffffff, 4, 0);
|
||||||
|
memcpy(wpt, name, 72);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
|
||||||
|
uint8_t *buf, uint32_t max_entries,
|
||||||
|
uint32_t part_start, uint32_t p_arr_crc)
|
||||||
|
{
|
||||||
|
static char *sig = "EFI PART";
|
||||||
|
static char revision[4] = {0x00, 0x00, 0x01, 0x00};
|
||||||
|
char *wpt;
|
||||||
|
uint32_t crc;
|
||||||
|
off_t back_lba;
|
||||||
|
|
||||||
|
memset(buf, 0, 128);
|
||||||
|
wpt = (char *) buf;
|
||||||
|
|
||||||
|
/* >>> Make signature adjustable */
|
||||||
|
memcpy(wpt, sig, 8); /* no trailing 0 */
|
||||||
|
wpt += 8;
|
||||||
|
|
||||||
|
memcpy(wpt, revision, 4);
|
||||||
|
wpt += 4;
|
||||||
|
iso_lsb_to_buf(&wpt, 92, 4, 0);
|
||||||
|
|
||||||
|
/* CRC will be inserted later */
|
||||||
|
wpt += 4;
|
||||||
|
|
||||||
|
/* reserved */
|
||||||
|
iso_lsb_to_buf(&wpt, 0, 4, 0);
|
||||||
|
/* Own LBA low 32 */
|
||||||
|
iso_lsb_to_buf(&wpt, 1, 4, 0);
|
||||||
|
/* Own LBA high 32 */
|
||||||
|
iso_lsb_to_buf(&wpt, 0, 4, 0);
|
||||||
|
|
||||||
|
/* Backup LBA is 1 hd block before image end */
|
||||||
|
back_lba = img_blocks * 4 - 1;
|
||||||
|
iso_lsb_to_buf(&wpt, (uint32_t) (back_lba & 0xffffffff), 4, 1);
|
||||||
|
iso_lsb_to_buf(&wpt, (uint32_t) (back_lba >> 32), 4, 1);
|
||||||
|
|
||||||
|
/* First usable LBA for partitions (4 entries per hd block) */
|
||||||
|
iso_lsb_to_buf(&wpt, part_start + max_entries / 4, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, 0, 4, 0);
|
||||||
|
|
||||||
|
/* Last usable LBA for partitions */
|
||||||
|
iso_lsb_to_buf(&wpt,
|
||||||
|
(uint32_t) ((back_lba - max_entries / 4) & 0xffffffff), 4, 1);
|
||||||
|
iso_lsb_to_buf(&wpt,
|
||||||
|
(uint32_t) ((back_lba - max_entries / 4) >> 32), 4, 1);
|
||||||
|
|
||||||
|
/* Disk GUID */
|
||||||
|
/* >>> Make adjustable */
|
||||||
|
iso_random_uuid(t, (uint8_t *) wpt);
|
||||||
|
wpt += 16;
|
||||||
|
|
||||||
|
/* Partition entries start */
|
||||||
|
iso_lsb_to_buf(&wpt, part_start, 4, 0);
|
||||||
|
iso_lsb_to_buf(&wpt, 0, 4, 0);
|
||||||
|
|
||||||
|
/* Number of partition entries */
|
||||||
|
iso_lsb_to_buf(&wpt, max_entries, 4, 0);
|
||||||
|
|
||||||
|
/* Size of a partition entry */
|
||||||
|
iso_lsb_to_buf(&wpt, 128, 4, 0);
|
||||||
|
|
||||||
|
/* CRC-32 of the partition array */
|
||||||
|
iso_lsb_to_buf(&wpt, p_arr_crc, 4, 0);
|
||||||
|
|
||||||
|
|
||||||
|
/* <<< Only for a first test */
|
||||||
|
if (wpt - (char *) buf != 92) {
|
||||||
|
iso_msgs_submit(0,
|
||||||
|
"program error : write_gpt_header_block : wpt != 92",
|
||||||
|
0, "FATAL", 0);
|
||||||
|
return ISO_ISOLINUX_CANT_PATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CRC-32 of this header while head_crc is 0 */
|
||||||
|
crc = iso_crc32_gpt((unsigned char *) buf, 128, 0);
|
||||||
|
wpt = ((char *) buf) + 16;
|
||||||
|
iso_lsb_to_buf(&wpt, crc, 4, 0);
|
||||||
|
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
|
||||||
|
static void poor_man_s_utf_16le(uint8_t gap_name[72])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = strlen((char *) gap_name) - 1; i >= 0; i--) {
|
||||||
|
gap_name[2 * i] = gap_name[i];
|
||||||
|
gap_name[2 * i + 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
>>> Need to memorize GPT copy for backup writer at tail
|
||||||
|
*/
|
||||||
|
static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks,
|
||||||
|
uint8_t *buf, uint32_t part_start)
|
||||||
|
{
|
||||||
|
static uint8_t basic_data_uuid[16] = {
|
||||||
|
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
|
||||||
|
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t p_arr_crc = 0, max_entries, part_end, goal;
|
||||||
|
uint64_t start_lba, end_lba;
|
||||||
|
int ret, i, gap_counter = 0, up_to;
|
||||||
|
struct iso_gpt_partition_request *req;
|
||||||
|
uint8_t gpt_name[72];
|
||||||
|
static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
|
||||||
|
|
||||||
|
#ifndef NIX
|
||||||
|
/* >>> Disable */
|
||||||
|
|
||||||
|
/* <<< ts B20526 : Dummy mock-up */
|
||||||
|
if (t->gpt_req_count <= 0) {
|
||||||
|
|
||||||
|
/* <<< ??? Move to system_area.h and publish as macro ?
|
||||||
|
Or to make_isohybrid_mbr.c ?
|
||||||
|
*/
|
||||||
|
static uint8_t hfs_uuid[16] = {
|
||||||
|
0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
|
||||||
|
0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
|
||||||
|
};
|
||||||
|
|
||||||
|
memset(gpt_name, 0, 72);
|
||||||
|
gpt_name[0] = 'T'; gpt_name[2] = '1';
|
||||||
|
strcpy((char *) gpt_name, "GPT Test 1");
|
||||||
|
poor_man_s_utf_16le(gpt_name);
|
||||||
|
/*
|
||||||
|
ret = iso_quick_gpt_entry(t, 16, 20, hfs_uuid, zero_uuid,
|
||||||
|
gpt_flags, gpt_name);
|
||||||
|
/ * >>> Caution: Size 90 causes intentional partition overlap error * /
|
||||||
|
ret = iso_quick_gpt_entry(t, 30, 90, hfs_uuid, zero_uuid,
|
||||||
|
gpt_flags, gpt_name);
|
||||||
|
*/
|
||||||
|
ret = iso_quick_gpt_entry(t, 30, 40, hfs_uuid, zero_uuid,
|
||||||
|
gpt_flags, gpt_name);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
strcpy((char *) gpt_name, "GPT Test 2");
|
||||||
|
poor_man_s_utf_16le(gpt_name);
|
||||||
|
ret = iso_quick_gpt_entry(t, 110, 60, basic_data_uuid, zero_uuid,
|
||||||
|
gpt_flags, gpt_name);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* NIX */
|
||||||
|
|
||||||
|
|
||||||
|
if (t->gpt_req_count == 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
/* Maximum number of GPT entries of 128 bytes until ISO PVD is reached */
|
||||||
|
if (part_start >= 64)
|
||||||
|
return ISO_ASSERT_FAILURE; /* miscomputation of part_start */
|
||||||
|
max_entries = (64 - part_start) * 4;
|
||||||
|
|
||||||
|
/* Sort and fill gaps */
|
||||||
|
qsort(t->gpt_req, t->gpt_req_count,
|
||||||
|
sizeof(struct iso_gpt_partition_request *), cmp_partition_request);
|
||||||
|
/* t->gpt_req_count will grow during the loop */
|
||||||
|
up_to = t->gpt_req_count + 1;
|
||||||
|
for (i = 0; i < up_to; i++) {
|
||||||
|
if (i < up_to - 1)
|
||||||
|
goal = t->gpt_req[i]->start_block;
|
||||||
|
else
|
||||||
|
goal = img_blocks;
|
||||||
|
if (i == 0) {
|
||||||
|
if (goal <= 16)
|
||||||
|
continue;
|
||||||
|
part_end = 16;
|
||||||
|
} else {
|
||||||
|
part_end = t->gpt_req[i - 1]->start_block +
|
||||||
|
t->gpt_req[i - 1]->block_count;
|
||||||
|
}
|
||||||
|
if (part_end > goal) {
|
||||||
|
iso_msg_submit(t->image->id, ISO_BOOT_GPT_OVERLAP, 0,
|
||||||
|
"Program error: GPT partitions %d and %d overlap by %lu blocks",
|
||||||
|
i - 1, i, part_end - goal);
|
||||||
|
return ISO_BOOT_GPT_OVERLAP;
|
||||||
|
}
|
||||||
|
if (part_end < goal) {
|
||||||
|
memset(gpt_name, 0, 72);
|
||||||
|
sprintf((char *) gpt_name, "Gap%d", gap_counter);
|
||||||
|
poor_man_s_utf_16le(gpt_name);
|
||||||
|
gap_counter++;
|
||||||
|
ret = iso_quick_gpt_entry(t, part_end, goal - part_end,
|
||||||
|
basic_data_uuid, zero_uuid,
|
||||||
|
gpt_flags, gpt_name);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Merge list of gap partitions with list of already sorted entries */
|
||||||
|
qsort(t->gpt_req, t->gpt_req_count,
|
||||||
|
sizeof(struct iso_gpt_partition_request *), cmp_partition_request);
|
||||||
|
|
||||||
|
if ((int) max_entries < t->gpt_req_count)
|
||||||
|
return ISO_BOOT_TOO_MANY_GPT;
|
||||||
|
|
||||||
|
/* Write the GPT entries to buf */
|
||||||
|
for (i = 0; i < t->gpt_req_count; i++) {
|
||||||
|
req = t->gpt_req[i];
|
||||||
|
start_lba = ((uint64_t) req->start_block) * 4;
|
||||||
|
end_lba = ((uint64_t) start_lba) + req->block_count * 4 - 1;
|
||||||
|
iso_write_gpt_entry(t, buf + 512 * part_start + 128 * i,
|
||||||
|
req->type_guid, req->partition_guid,
|
||||||
|
start_lba, end_lba, req->flags, req->name);
|
||||||
|
}
|
||||||
|
for (; i < (int) max_entries; i++)
|
||||||
|
memset(buf + 512 * part_start + 128 * i, 0, 128);
|
||||||
|
|
||||||
|
p_arr_crc = iso_crc32_gpt((unsigned char *) buf + 512 * part_start,
|
||||||
|
128 * max_entries, 0);
|
||||||
|
ret = iso_write_gpt_header_block(t, img_blocks, buf + 512, max_entries,
|
||||||
|
part_start, p_arr_crc);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
int ret, int_img_blocks, sa_type, i, will_append = 0;
|
||||||
int first_partition = 1, last_partition = 4;
|
int first_partition = 1, last_partition = 4;
|
||||||
uint32_t img_blocks;
|
uint32_t img_blocks, gpt_part_start;
|
||||||
|
|
||||||
if ((t == NULL) || (buf == NULL)) {
|
if ((t == NULL) || (buf == NULL)) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
@ -963,21 +1248,42 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If APM entries were submitted to iso_register_apm_entry(), then they
|
/* If APM entries were submitted to iso_register_apm_entry(), then they
|
||||||
get sprinkled over the system area before any other data get inserted.
|
get sprinkled over the system area after the system area template was
|
||||||
Note that Block0 of the APM is not written but is in the responsibility
|
loaded and before any other data get inserted.
|
||||||
of the MBR template. Its block size MUST match t->apm_block_size.
|
Note that if APM and MBR get combined, then the first 8 bytes of the MBR
|
||||||
|
template must be replaceable by:
|
||||||
|
{0x45, 0x52, 0x08 0x00, 0xeb, 0x02, 0xff, 0xff}
|
||||||
|
|
||||||
>>> ts B20526
|
>>> ts B20526
|
||||||
>>> This does not care for eventual image enlargements in last minute.
|
>>> This does not care for eventual image enlargements in last minute.
|
||||||
>>> A sa_type, that does this, will have to adjust the last APM entry
|
>>> A sa_type, that does this, will have to adjust the last APM entry
|
||||||
>>> if exactness matters.
|
>>> if exactness matters.
|
||||||
*/
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
ret = iso_write_apm(t, img_blocks, buf);
|
ret = iso_write_apm(t, img_blocks, buf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
iso_msg_submit(t->image->id, ret, 0,
|
iso_msg_submit(t->image->id, ret, 0,
|
||||||
"Cannot set up Apple Partition Map");
|
"Cannot set up Apple Partition Map");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
gpt_part_start = 0;
|
||||||
|
if (t->apm_req_count > 0)
|
||||||
|
gpt_part_start = (t->apm_req_count + 1) * (t->apm_block_size / 512);
|
||||||
|
if (gpt_part_start < 2)
|
||||||
|
gpt_part_start = 2;
|
||||||
|
else if (gpt_part_start >= 64)
|
||||||
|
return ISO_BOOT_TOO_MANY_GPT;
|
||||||
|
ret = iso_write_gpt(t, img_blocks, buf, gpt_part_start);
|
||||||
|
if (ret < 0) {
|
||||||
|
iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (sa_type == 0 && (t->system_area_options & 1)) {
|
if (sa_type == 0 && (t->system_area_options & 1)) {
|
||||||
/* Write GRUB protective msdos label, i.e. a simple partition table */
|
/* Write GRUB protective msdos label, i.e. a simple partition table */
|
||||||
@ -1205,6 +1511,24 @@ int iso_register_apm_entry(Ecma119Image *t,
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int iso_register_gpt_entry(Ecma119Image *t,
|
||||||
|
struct iso_gpt_partition_request *req, int flag)
|
||||||
|
{
|
||||||
|
struct iso_gpt_partition_request *entry;
|
||||||
|
|
||||||
|
if (t->gpt_req_count >= ISO_GPT_ENTRIES_MAX)
|
||||||
|
return ISO_BOOT_TOO_MANY_GPT;
|
||||||
|
entry = calloc(1, sizeof(struct iso_gpt_partition_request));
|
||||||
|
if (entry == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
|
||||||
|
memcpy(entry, req, sizeof(struct iso_gpt_partition_request));
|
||||||
|
t->gpt_req[t->gpt_req_count] = entry;
|
||||||
|
t->gpt_req_count++;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Libisofs_with_uuid_generatE
|
#ifdef Libisofs_with_uuid_generatE
|
||||||
|
|
||||||
static void swap_uuid(void *u_pt)
|
static void swap_uuid(void *u_pt)
|
||||||
|
@ -126,4 +126,68 @@ void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
|
|||||||
void iso_random_8byte(Ecma119Image *t, uint8_t result[8]);
|
void iso_random_8byte(Ecma119Image *t, uint8_t result[8]);
|
||||||
|
|
||||||
|
|
||||||
|
/* The parameter struct for production of a single GPT entry.
|
||||||
|
See also the partial GPT description in doc/boot_sectors.txt.
|
||||||
|
The list of entries is stored in Ecma119Image.gpt_req.
|
||||||
|
The GPT header block at byte 0x200 will get produced automatically.
|
||||||
|
The GPT entries will be stored after the Apple Partition Map, if such
|
||||||
|
gets generated too. Both partition descriptions must fit into the 32 KiB
|
||||||
|
of the ISO 9660 System Area.
|
||||||
|
|
||||||
|
GPT can be combined with APM only if (Ecma119Image.apm_block_size > 512).
|
||||||
|
Otherwise, block 1 of APM and GPT header block would collide.
|
||||||
|
So Ecma119Image.apm_block_size is set automatically to 2048 if at least
|
||||||
|
one GPT entry is requested. (One could try 1024 ...).
|
||||||
|
*/
|
||||||
|
struct iso_gpt_partition_request {
|
||||||
|
|
||||||
|
/* Always given in blocks of 2 KiB.
|
||||||
|
Written to the ISO image in blocks of 512.
|
||||||
|
*/
|
||||||
|
uint32_t start_block;
|
||||||
|
uint32_t block_count;
|
||||||
|
|
||||||
|
/* The registered GUID which defines the partition type */
|
||||||
|
uint8_t type_guid[16];
|
||||||
|
|
||||||
|
/* An individual GUID which shall be unique to the partition.
|
||||||
|
If the caller submits 0...0 then a (weak) random uuid will be generated.
|
||||||
|
*/
|
||||||
|
uint8_t partition_guid[16];
|
||||||
|
|
||||||
|
/* bit0= "System Partition" Do not alter,
|
||||||
|
bit2= Legacy BIOS bootable (MBR partition type 0x80)
|
||||||
|
bit60= read-only
|
||||||
|
*/
|
||||||
|
uint64_t flags;
|
||||||
|
|
||||||
|
/* Fill with text encoded as UTF-16LE.
|
||||||
|
All 72 bytes get copied to the system area.
|
||||||
|
Take care to pad up short strings by 0.
|
||||||
|
*/
|
||||||
|
uint8_t name[72];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Copies the content of req and registers it in t.gpt_req[].
|
||||||
|
I.e. after the call the submitted storage of req can be disposed or re-used.
|
||||||
|
Submit 0 as value flag.
|
||||||
|
*/
|
||||||
|
int iso_register_gpt_entry(Ecma119Image *t,
|
||||||
|
struct iso_gpt_partition_request *req, int flag);
|
||||||
|
|
||||||
|
/* Convenience frontend for iso_register_gpt_entry().
|
||||||
|
name has to be already encoded as UTF-16LE.
|
||||||
|
*/
|
||||||
|
int iso_quick_gpt_entry(Ecma119Image *t,
|
||||||
|
uint32_t start_block, uint32_t block_count,
|
||||||
|
uint8_t type_guid[16], uint8_t partition_guid[16],
|
||||||
|
uint64_t flags, uint8_t name[72]);
|
||||||
|
|
||||||
|
|
||||||
|
/* Internal helper that will be used by system_area.c and make_isohybrid_mbr.c
|
||||||
|
*/
|
||||||
|
int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
|
||||||
|
uint8_t *buf, uint32_t max_entries,
|
||||||
|
uint32_t part_start, uint32_t p_arr_crc);
|
||||||
|
|
||||||
#endif /* SYSTEM_AREA_H_ */
|
#endif /* SYSTEM_AREA_H_ */
|
||||||
|
@ -1355,6 +1355,18 @@ void iso_bb(uint8_t *buf, uint32_t num, int bytes)
|
|||||||
iso_msb(buf+bytes, num, bytes);
|
iso_msb(buf+bytes, num, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* An alternative to iso_lsb() which advances the write pointer
|
||||||
|
*/
|
||||||
|
int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag)
|
||||||
|
{
|
||||||
|
int b, bits;
|
||||||
|
|
||||||
|
bits = bytes * 8;
|
||||||
|
for (b = 0; b < bits; b += 8)
|
||||||
|
*((unsigned char *) ((*wpt)++)) = (value >> b) & 0xff;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
|
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -232,6 +232,10 @@ void iso_lsb(uint8_t *buf, uint32_t num, int bytes);
|
|||||||
void iso_msb(uint8_t *buf, uint32_t num, int bytes);
|
void iso_msb(uint8_t *buf, uint32_t num, int bytes);
|
||||||
void iso_bb(uint8_t *buf, uint32_t num, int bytes);
|
void iso_bb(uint8_t *buf, uint32_t num, int bytes);
|
||||||
|
|
||||||
|
/* An alternative to iso_lsb() which advances the write pointer
|
||||||
|
*/
|
||||||
|
int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag);
|
||||||
|
|
||||||
uint32_t iso_read_lsb(const uint8_t *buf, int bytes);
|
uint32_t iso_read_lsb(const uint8_t *buf, int bytes);
|
||||||
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user