Inner API for requesting MBR partition table entries.

This commit is contained in:
Thomas Schmitt 2012-06-11 13:05:46 +02:00
parent 1de0284eaa
commit 0897896713
6 changed files with 180 additions and 3 deletions

View File

@ -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->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++) for (i = 0; (int) i < t->gpt_req_count; i++)
if (t->gpt_req[i] != NULL) if (t->gpt_req[i] != NULL)
free(t->gpt_req[i]); free(t->gpt_req[i]);
@ -1891,6 +1894,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->apm_block_size = 512; target->apm_block_size = 512;
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++) for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
target->apm_req[i] = NULL; 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++) for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
target->gpt_req[i] = NULL; target->gpt_req[i] = NULL;
target->gpt_part_start = 0; target->gpt_part_start = 0;

View File

@ -76,6 +76,10 @@
*/ */
#define ISO_APM_ENTRIES_MAX 63 #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 /* The theoretical maximum number of GPT entries in the System Area of an
ISO image: ISO image:
MBR plus GPT header block plus 248 GPT entries of 128 bytes each. 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. */ /* 512 by default. May be changed to 2048 before writer thread starts. */
int apm_block_size; 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 /* GPT description. To be composed during IsoImageWriter
method ->compute_data_blocks() by calling iso_register_gpt_entry(). method ->compute_data_blocks() by calling iso_register_gpt_entry().
Make sure that the composing writers get registered before the Make sure that the composing writers get registered before the

View File

@ -7251,6 +7251,12 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
/** Overlapping GPT entries requested (FAILURE, HIGH, -386) */ /** Overlapping GPT entries requested (FAILURE, HIGH, -386) */
#define ISO_BOOT_GPT_OVERLAP 0xE830FE7E #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: /* Internal developer note:

View File

@ -482,6 +482,10 @@ const char *iso_error_to_msg(int errcode)
return "Too many GPT entries requested"; return "Too many GPT entries requested";
case ISO_BOOT_GPT_OVERLAP: case ISO_BOOT_GPT_OVERLAP:
return "Overlapping GPT entries requested"; 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: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -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 * 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, static void iso_write_gpt_entry(Ecma119Image *t, uint8_t *buf,
uint8_t type_guid[16], uint8_t part_uuid[16], uint8_t type_guid[16], uint8_t part_uuid[16],
uint64_t start_lba, uint64_t end_lba, 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); t->gpt_part_start, p_arr_crc);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* >>> Memorize GPT copy for backup writer at tail */;
return ISO_SUCCESS; return ISO_SUCCESS;
} }
@ -1278,6 +1361,12 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
"Cannot set up Apple Partition Map"); "Cannot set up Apple Partition Map");
return ret; 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); ret = iso_write_gpt(t, img_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");
@ -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, int iso_register_gpt_entry(Ecma119Image *t,
struct iso_gpt_partition_request *req, int flag) struct iso_gpt_partition_request *req, int flag)
{ {
@ -1738,6 +1845,7 @@ static int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
t->curblock++; t->curblock++;
/* The ISO block number after the backup GPT header */ /* The ISO block number after the backup GPT header */
t->gpt_backup_end = t->curblock; t->gpt_backup_end = t->curblock;
return ISO_SUCCESS; return ISO_SUCCESS;
} }

View File

@ -65,6 +65,50 @@ int iso_read_mipsel_elf(Ecma119Image *t, int flag);
int iso_compute_append_partitions(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. /* The parameter struct for production of a single Apple Partition Map entry.
See also the partial APM description in doc/boot_sectors.txt. See also the partial APM description in doc/boot_sectors.txt.
The list of entries is stored in Ecma119Image.apm_req. The list of entries is stored in Ecma119Image.apm_req.