Introduced opportunity to choose an MBR partition number with

struct iso_mbr_partition_request and iso_quick_mbr_entry().
This commit is contained in:
Thomas Schmitt 2012-06-21 12:29:00 +02:00
parent bbd198a81b
commit 85bedae639
2 changed files with 82 additions and 18 deletions

View File

@ -776,11 +776,18 @@ 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)
uint8_t type_byte, uint8_t status_byte,
int desired_slot)
{
int ret;
struct iso_mbr_partition_request *entry;
ret = iso_mbr_entry_slot_is_free(t, desired_slot);
if (ret < 0)
desired_slot = 0;
else if (ret == 0)
return ISO_BOOT_MBR_COLLISION;
entry = calloc(1, sizeof(struct iso_mbr_partition_request));
if (entry == NULL)
return ISO_OUT_OF_MEM;
@ -788,14 +795,30 @@ int iso_quick_mbr_entry(Ecma119Image *t,
entry->block_count = block_count;
entry->type_byte = type_byte;
entry->status_byte = status_byte;
entry->desired_slot = desired_slot;
ret = iso_register_mbr_entry(t, entry, 0);
free(entry);
return ret;
}
int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot)
{
int i;
if (slot < 0 || slot > ISO_MBR_ENTRIES_MAX)
return -1;
if (slot == 0)
return 1;
for (i = 0; i < t->mbr_req_count; i++)
if (t->mbr_req[i]->desired_slot == slot)
return 0;
return 1;
}
/**
* Compare the start_sectors of two iso_apm_partition_request
* Compare the block interval positions of two iso_apm_partition_request
*/
static
int cmp_partition_request(const void *f1, const void *f2)
@ -1067,17 +1090,17 @@ 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;
int i, ret, req_of_slot[ISO_MBR_ENTRIES_MAX], q, j;
#ifdef NIX
/* Disabled */
/* <<< Dummy mock-up */
if (t->mbr_req_count <= 0) {
ret = iso_quick_mbr_entry(t, 0, 0, 0xee, 0);
ret = iso_quick_mbr_entry(t, 0, 0, 0xee, 0, 0);
if (ret < 0)
return ret;
ret = iso_quick_mbr_entry(t, 100, 0, 0x0c, 0x80);
ret = iso_quick_mbr_entry(t, 100, 0, 0x0c, 0x80, 1);
if (ret < 0)
return ret;
}
@ -1110,22 +1133,43 @@ static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
t->mbr_req[i]->start_block;
}
/* >>> Permutate ? */
/* Assign requested entries to slot numbers */
for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++)
req_of_slot[i] = -1;
for (i = 0; i < t->mbr_req_count; i++) {
if (t->mbr_req[i]->desired_slot < 1 ||
t->mbr_req[i]->desired_slot > ISO_MBR_ENTRIES_MAX)
continue;
if (req_of_slot[t->mbr_req[i]->desired_slot - 1] >= 0)
return ISO_BOOT_MBR_COLLISION;
req_of_slot[t->mbr_req[i]->desired_slot - 1] = i;
}
for (i = 0; i < t->mbr_req_count; i++) {
if (t->mbr_req[i]->desired_slot > 0)
continue;
for (j = 0; j < ISO_MBR_ENTRIES_MAX; j++)
if (req_of_slot[j] < 0)
break;
if (j >= ISO_MBR_ENTRIES_MAX)
return ISO_BOOT_TOO_MANY_MBR;
req_of_slot[j] = i;
}
/* 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)
q = req_of_slot[i];
if (q < 0)
continue;
if (t->mbr_req[i]->block_count == 0)
if (t->mbr_req[q]->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,
ret = write_mbr_partition_entry(i + 1, (int) t->mbr_req[q]->type_byte,
t->mbr_req[q]->start_block, t->mbr_req[q]->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;
buf[446 + i * 16] = t->mbr_req[q]->status_byte;
}
return ISO_SUCCESS;
}
@ -2152,7 +2196,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
if (t->prep_partition != NULL || t->fat || will_have_gpt ||
t->mbr_req_count > 0)
return ISO_BOOT_MBR_OVERLAP;
ret = iso_quick_mbr_entry(t, (uint32_t) 0, (uint32_t) 0, 0x96, 0);
ret = iso_quick_mbr_entry(t, (uint32_t) 0, (uint32_t) 0, 0x96, 0, 0);
if (ret < 0)
return ret;
return ISO_SUCCESS;
@ -2167,12 +2211,13 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
if (t->prep_part_size > 0 || t->fat || will_have_gpt) {
/* Protecting MBR entry for ISO start or whole ISO */
ret = iso_quick_mbr_entry(t, (uint32_t) t->partition_offset,
(uint32_t) 0, will_have_gpt ? 0xee : 0xcd, 0);
(uint32_t) 0, will_have_gpt ? 0xee : 0xcd, 0, 0);
if (ret < 0)
return ret;
}
if (t->prep_part_size > 0) {
ret = iso_quick_mbr_entry(t, t->curblock, t->prep_part_size, 0x41, 0);
ret = iso_quick_mbr_entry(t, t->curblock, t->prep_part_size, 0x41,
0, 0);
if (ret < 0)
return ret;
t->curblock += t->prep_part_size;
@ -2180,7 +2225,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
if (t->prep_part_size > 0 || t->fat) {
/* FAT partition or protecting MBR entry for ISO end */
ret = iso_quick_mbr_entry(t, (uint32_t) t->curblock, (uint32_t) 0,
t->fat ? 0x0c : 0xcd, 0);
t->fat ? 0x0c : 0xcd, 0, 0);
if (ret < 0)
return ret;
}

View File

@ -67,7 +67,9 @@ 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.
No sorting by start sector and gap filling is done before the System Area
gets written. But the entries may get assigned to a desired slot number
in the table.
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
@ -90,7 +92,15 @@ struct iso_mbr_partition_request {
/* 0x80 = bootable */
uint8_t status_byte;
/* >>> Is a permutation of entries needed ? */
/* If >= 1 && <= 4 : The partition slot number in MBR.
If more than one partition desires the same slot, then an error
ISO_BOOT_MBR_COLLISION occurs at registration time.
Use iso_mbr_entry_slot_is_free() to detect this in advance.
If desired_slot is 0, then the partition entry is put into the
lowest MBR slot that is not occupied by an entry with desired_slot > 0
or by an entry that was registered before this entry.
*/
int desired_slot;
};
@ -106,7 +116,16 @@ int iso_register_mbr_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);
uint8_t type_byte, uint8_t status_byte,
int desired_slot);
/* Peek in advance whether a desired slot number is already occupied by a
registered MBR entry.
Parameter slot may be between 0 and 4. 0 always returns "free".
Return value is 0 if occupied, 1 if free, and -1 if the slot number is
out of range.
*/
int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot);
/* The parameter struct for production of a single Apple Partition Map entry.