Inner API for requesting MBR partition table entries.
This commit is contained in:
parent
1de0284eaa
commit
0897896713
@ -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->mbr_req_count; i++)
|
||||
if (t->mbr_req[i] != NULL)
|
||||
free(t->mbr_req[i]);
|
||||
for (i = 0; (int) i < t->gpt_req_count; i++)
|
||||
if (t->gpt_req[i] != NULL)
|
||||
free(t->gpt_req[i]);
|
||||
@ -1891,6 +1894,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->apm_block_size = 512;
|
||||
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
|
||||
target->apm_req[i] = NULL;
|
||||
for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++)
|
||||
target->mbr_req[i] = NULL;
|
||||
for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
|
||||
target->gpt_req[i] = NULL;
|
||||
target->gpt_part_start = 0;
|
||||
|
@ -76,6 +76,10 @@
|
||||
*/
|
||||
#define ISO_APM_ENTRIES_MAX 63
|
||||
|
||||
/* The maximum number of MBR partition table entries.
|
||||
*/
|
||||
#define ISO_MBR_ENTRIES_MAX 4
|
||||
|
||||
/* 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.
|
||||
@ -815,6 +819,12 @@ struct ecma119_image
|
||||
/* 512 by default. May be changed to 2048 before writer thread starts. */
|
||||
int apm_block_size;
|
||||
|
||||
/* MBR partition table description. To be composed during IsoImageWriter
|
||||
method ->compute_data_blocks() by calling iso_register_mbr_entry().
|
||||
*/
|
||||
struct iso_mbr_partition_request *mbr_req[ISO_MBR_ENTRIES_MAX];
|
||||
int mbr_req_count;
|
||||
|
||||
/* GPT description. To be composed during IsoImageWriter
|
||||
method ->compute_data_blocks() by calling iso_register_gpt_entry().
|
||||
Make sure that the composing writers get registered before the
|
||||
|
@ -7251,6 +7251,12 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
|
||||
/** Overlapping GPT entries requested (FAILURE, HIGH, -386) */
|
||||
#define ISO_BOOT_GPT_OVERLAP 0xE830FE7E
|
||||
|
||||
/** Too many MBR partition entries requested (FAILURE, HIGH, -387) */
|
||||
#define ISO_BOOT_TOO_MANY_MBR 0xE830FE7D
|
||||
|
||||
/** Overlapping MBR entries requested (FAILURE, HIGH, -388) */
|
||||
#define ISO_BOOT_MBR_OVERLAP 0xE830FE7C
|
||||
|
||||
|
||||
|
||||
/* Internal developer note:
|
||||
|
@ -482,6 +482,10 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "Too many GPT entries requested";
|
||||
case ISO_BOOT_GPT_OVERLAP:
|
||||
return "Overlapping GPT entries requested";
|
||||
case ISO_BOOT_TOO_MANY_MBR:
|
||||
return "Too many MBR partition entries requested";
|
||||
case ISO_BOOT_MBR_OVERLAP:
|
||||
return "Overlapping MBR entries requested";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -750,6 +750,26 @@ int iso_quick_gpt_entry(Ecma119Image *t,
|
||||
}
|
||||
|
||||
|
||||
int iso_quick_mbr_entry(Ecma119Image *t,
|
||||
uint32_t start_block, uint32_t block_count,
|
||||
uint8_t type_byte, uint8_t status_byte)
|
||||
{
|
||||
int ret;
|
||||
struct iso_mbr_partition_request *entry;
|
||||
|
||||
entry = calloc(1, sizeof(struct iso_mbr_partition_request));
|
||||
if (entry == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
entry->start_block = start_block;
|
||||
entry->block_count = block_count;
|
||||
entry->type_byte = type_byte;
|
||||
entry->status_byte = status_byte;
|
||||
ret = iso_register_mbr_entry(t, entry, 0);
|
||||
free(entry);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare the start_sectors of two iso_apm_partition_request
|
||||
*/
|
||||
@ -1000,6 +1020,72 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
}
|
||||
|
||||
|
||||
static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
#ifdef NIX
|
||||
/* Disabled */
|
||||
|
||||
/* <<< Dummy mock-up */
|
||||
if (t->mbr_req_count <= 0) {
|
||||
ret = iso_quick_mbr_entry(t, 0, 0, 0xee, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_quick_mbr_entry(t, 100, 0, 0x0c, 0x80);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
#endif /* NIX */
|
||||
|
||||
if (t->mbr_req_count <= 0)
|
||||
return 2;
|
||||
|
||||
/* >>> Sort by start block ? */
|
||||
|
||||
/* Adjust partition ends */
|
||||
for (i = 0; i < t->mbr_req_count; i++) {
|
||||
if (i > 0) {
|
||||
if (t->mbr_req[i]->start_block <= t->mbr_req[i - 1]->start_block &&
|
||||
!(t->mbr_req[i]->block_count == 0 &&
|
||||
t->mbr_req[i]->start_block ==
|
||||
t->mbr_req[i - 1]->start_block))
|
||||
return ISO_BOOT_MBR_OVERLAP;
|
||||
if (t->mbr_req[i - 1]->start_block +
|
||||
t->mbr_req[i - 1]->block_count > t->mbr_req[i]->start_block)
|
||||
return ISO_BOOT_MBR_OVERLAP;
|
||||
}
|
||||
if (t->mbr_req[i]->block_count != 0)
|
||||
continue;
|
||||
if (i < t->mbr_req_count - 1)
|
||||
t->mbr_req[i]->block_count = t->mbr_req[i + 1]->start_block -
|
||||
t->mbr_req[i]->start_block;
|
||||
else
|
||||
t->mbr_req[i]->block_count = img_blocks -
|
||||
t->mbr_req[i]->start_block;
|
||||
}
|
||||
|
||||
/* >>> Permutate ? */
|
||||
|
||||
/* Write partition slots */
|
||||
for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++) {
|
||||
memset(buf + 446 + i * 16, 0, 16);
|
||||
if (i >= t->mbr_req_count)
|
||||
continue;
|
||||
if (t->mbr_req[i]->block_count == 0)
|
||||
continue;
|
||||
ret = write_mbr_partition_entry(i + 1, (int) t->mbr_req[i]->type_byte,
|
||||
t->mbr_req[i]->start_block, t->mbr_req[i]->block_count,
|
||||
t->partition_secs_per_head, t->partition_heads_per_cyl,
|
||||
buf, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf[446 + i * 16] = t->mbr_req[i]->status_byte;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
@ -1205,9 +1291,6 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
t->gpt_part_start, p_arr_crc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* >>> Memorize GPT copy for backup writer at tail */;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1278,6 +1361,12 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
"Cannot set up Apple Partition Map");
|
||||
return ret;
|
||||
}
|
||||
ret = iso_write_mbr(t, img_blocks, buf);
|
||||
if (ret < 0) {
|
||||
iso_msg_submit(t->image->id, ret, 0,
|
||||
"Cannot set up MBR partition table");
|
||||
return ret;
|
||||
}
|
||||
ret = iso_write_gpt(t, img_blocks, buf);
|
||||
if (ret < 0) {
|
||||
iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT");
|
||||
@ -1511,6 +1600,24 @@ int iso_register_apm_entry(Ecma119Image *t,
|
||||
}
|
||||
|
||||
|
||||
int iso_register_mbr_entry(Ecma119Image *t,
|
||||
struct iso_mbr_partition_request *req, int flag)
|
||||
{
|
||||
struct iso_mbr_partition_request *entry;
|
||||
|
||||
if (t->mbr_req_count >= ISO_MBR_ENTRIES_MAX)
|
||||
return ISO_BOOT_TOO_MANY_MBR;
|
||||
entry = calloc(1, sizeof(struct iso_mbr_partition_request));
|
||||
if (entry == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
memcpy(entry, req, sizeof(struct iso_mbr_partition_request));
|
||||
t->mbr_req[t->mbr_req_count] = entry;
|
||||
t->mbr_req_count++;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_register_gpt_entry(Ecma119Image *t,
|
||||
struct iso_gpt_partition_request *req, int flag)
|
||||
{
|
||||
@ -1738,6 +1845,7 @@ static int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
t->curblock++;
|
||||
/* The ISO block number after the backup GPT header */
|
||||
t->gpt_backup_end = t->curblock;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,50 @@ int iso_read_mipsel_elf(Ecma119Image *t, int flag);
|
||||
int iso_compute_append_partitions(Ecma119Image *t, int flag);
|
||||
|
||||
|
||||
/* The parameter struct for production of a single MBR partition entry.
|
||||
See also the description of MBR in doc/boot_sectors.txt.
|
||||
No sorting and gap filling is done before the System Area gets written.
|
||||
Requested entries with block_count == 0 get expanded to the start of
|
||||
the next requested entry resp. to image end, if no entry follows.
|
||||
start_block of a follwing entry must be at least a high as the sum of
|
||||
start_block and block_count of the previous entry.
|
||||
Empty requested entries will be represented as 16 bytes of 0.
|
||||
*/
|
||||
struct iso_mbr_partition_request {
|
||||
|
||||
/* Always given in blocks of 2 KiB */
|
||||
uint32_t start_block;
|
||||
|
||||
/* A block count of 0 means that the partition reaches up to the start of
|
||||
the next one.
|
||||
*/
|
||||
uint32_t block_count;
|
||||
|
||||
/* Partition type */
|
||||
uint8_t type_byte;
|
||||
|
||||
/* 0x80 = bootable */
|
||||
uint8_t status_byte;
|
||||
|
||||
/* >>> Is a permutation of entries needed ? */
|
||||
|
||||
};
|
||||
|
||||
/* Copies the content of req and registers it in t.mbr_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_mbr_entry(Ecma119Image *t,
|
||||
struct iso_mbr_partition_request *req, int flag);
|
||||
|
||||
/* Convenience frontend for iso_register_mbr_entry().
|
||||
name and type are 0-terminated strings, which may get silently truncated.
|
||||
*/
|
||||
int iso_quick_mbr_entry(Ecma119Image *t,
|
||||
uint32_t start_block, uint32_t block_count,
|
||||
uint8_t type_byte, uint8_t status_byte);
|
||||
|
||||
|
||||
/* The parameter struct for production of a single Apple Partition Map entry.
|
||||
See also the partial APM description in doc/boot_sectors.txt.
|
||||
The list of entries is stored in Ecma119Image.apm_req.
|
||||
|
Loading…
Reference in New Issue
Block a user