First stage of implementation of GPT production.

The writer class for the backup GPT is not implemented yet.
This commit is contained in:
Thomas Schmitt 2012-06-02 19:32:22 +02:00
parent 714ef6493a
commit bcd4b88319
10 changed files with 462 additions and 114 deletions

View File

@ -125,6 +125,9 @@ void ecma119_image_free(Ecma119Image *t)
for (i = 0; (int) i < t->apm_req_count; i++)
if (t->apm_req[i] != NULL)
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);
}
@ -1881,13 +1884,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->hfsplus_blessed[i] != NULL)
iso_node_ref(target->hfsplus_blessed[i]);
}
/* Note: Set apm_block_size to 2048, if desired, before pthread_create()
at the end of this function.
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;
/* Set apm_block_size to 2048, if desired, before pthread_create()
at the end of this function.
Register any Apple Partition Map entries before pthread_create().
*/
for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
target->gpt_req[i] = NULL;
/*
* 2. Based on those options, create needed writers: iso, joliet...

View File

@ -70,10 +70,18 @@
#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
/* 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.
@ -803,6 +811,12 @@ struct ecma119_image
/* 512 by default. May be changed to 2048 before writer thread starts. */
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]

View File

@ -1,6 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License version 2

View File

@ -7209,6 +7209,12 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
/** Overlapping Apple Partition Map entries requested (FAILURE, HIGH, -384) */
#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:

View File

@ -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],
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);
}
#ifdef NIX
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
start_lba = ;
end_lba = ;
>>> replace write_gpt_entry by iso_quick_gpt_entry
write_gpt_entry(t, buf + 512 * part_start, basic_data_uuid,
off_t start_lba, off_t end_lba, uint8_t flags[8],
uint8_t name[72])
@ -530,7 +517,7 @@ static int write_gpt_array(Ecma119Image *t, char *buf, uint32_t part_start)
else
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;
}
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;
}
#endif /* NIX */
/*
@ -627,7 +539,7 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
uint32_t id, part, nominal_part_size;
off_t hd_img_blocks, hd_boot_lba;
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 gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
/* For generating a weak random number */
@ -729,9 +641,12 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
/* >>> ISOHYBRID : write primary GPT and compute p_arr_crc */;
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,
part_start, p_arr_crc);
ret = iso_write_gpt_header_block(t, (uint32_t) *img_blocks,
buf + 512, max_gpt_entries,
part_start, p_arr_crc);
if (ret < 0)
return ret;
}

View File

@ -478,6 +478,10 @@ const char *iso_error_to_msg(int errcode)
return "Too many Apple Partition Map entries requested";
case ISO_BOOT_APM_OVERLAP:
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:
return "Unknown error";
}

View File

@ -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
*/
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);
r2 = *((struct iso_apm_partition_request **) f2);
r1 = *((struct iso_partition_request **) f1);
r2 = *((struct iso_partition_request **) f2);
if (r1->start_block < r2->start_block)
return -1;
if (r1->start_block > r2->start_block)
@ -740,6 +769,7 @@ int cmp_apm_partition_request(const void *f1, const void *f2)
return 0;
}
/* @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.
*/
@ -842,7 +872,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
/* Sort and fill gaps */
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 */
up_to = t->apm_req_count + 1;
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) {
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);
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 */
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 */
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 ret, int_img_blocks, sa_type, i, will_append = 0;
int first_partition = 1, last_partition = 4;
uint32_t img_blocks;
uint32_t img_blocks, gpt_part_start;
if ((t == NULL) || (buf == NULL)) {
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
get sprinkled over the system area before any other data get inserted.
Note that Block0 of the APM is not written but is in the responsibility
of the MBR template. Its block size MUST match t->apm_block_size.
get sprinkled over the system area after the system area template was
loaded and before any other data get inserted.
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
>>> 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
>>> 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);
if (ret < 0) {
iso_msg_submit(t->image->id, ret, 0,
"Cannot set up Apple Partition Map");
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)) {
/* 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;
}
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
static void swap_uuid(void *u_pt)

View File

@ -126,4 +126,68 @@ void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
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_ */

View File

@ -1355,6 +1355,18 @@ void iso_bb(uint8_t *buf, uint32_t num, int 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)
{
int i;

View File

@ -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_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_msb(const uint8_t *buf, int bytes);