New option bits 2 to 7 with el_torito_set_isolinux_options()
This commit is contained in:
parent
27277914c6
commit
bab3cf0c7c
@ -895,7 +895,7 @@ Sources:
|
||||
Mail conversations with Vladimir Serbinenko.
|
||||
|
||||
|
||||
PReP boots via a MBR partition containing only raw ELF and having type 0x42.
|
||||
PReP boots via a MBR partition containing only raw ELF and having type 0x41.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -1006,16 +1006,16 @@ firmware. It disobeys some of the prescriptions in the previous chapter.
|
||||
446 - 461 | mbr_entry1 | Partition table entry 1 describing the size of
|
||||
| | the ISO image plus the backup GPT, padded up to
|
||||
| | the next full MiB.
|
||||
462 - 477 | mbr_entry2 | Entry 2 describing the UEFI VFAT boot image.
|
||||
462 - 477 | mbr_entry2 | Entry 2 describing the EFI VFAT boot image.
|
||||
478 - 493 | mbr_entry3 | Entry 3 describing the HFS+ boot image.
|
||||
| |
|
||||
512 - 1023 | gpt_head | GPT header describing the GPT partition array.
|
||||
1024 - 2047 | unused |
|
||||
2048 - 4095 | apm_entry1 | APM entry 1 describing APM entries 1 to 3.
|
||||
4096 - 6143 | apm_entry2 | APM entry 2 describing the UEFI VFAT boot image.
|
||||
4096 - 6143 | apm_entry2 | APM entry 2 describing the EFI VFAT boot image.
|
||||
6144 - 8195 | apm_entry3 | APM entry 3 describing the HFS+ boot image.
|
||||
8192 - 8319 | gpt_entry1 | GPT partition entry 1 for the ISO image size.
|
||||
8320 - 8447 | gpt_entry2 | GPT partition entry 2 for UEFI VFAT boot image,
|
||||
8320 - 8447 | gpt_entry2 | GPT partition entry 2 for EFI VFAT boot image,
|
||||
8448 - 8575 | gpt_entry3 | GPT partition entry 3 for the HFS+ boot image.
|
||||
8576 - 24575 | gtp_empty | Empty GPT partition entries 4 to 128.
|
||||
24576 - 32767 | unused |
|
||||
@ -1376,7 +1376,7 @@ System Area may contain simultaneously:
|
||||
|
||||
MBR Partitions:
|
||||
0xee from 0 to PREP-1, protective partition, announcing presence of GPT
|
||||
0x42 from PREP to HFAT-1, PreP partition
|
||||
0x41 from PREP to HFAT-1, PreP partition
|
||||
0x0c from HFAT to END-1, FAT partition, bootable bit on
|
||||
0x00 Empty partition
|
||||
|
||||
|
@ -1918,12 +1918,17 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
iso_node_ref(target->hfsplus_blessed[i]);
|
||||
}
|
||||
target->apm_block_size = 512;
|
||||
target->apm_req_count = 0;
|
||||
target->apm_req_flags = 0;
|
||||
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;
|
||||
target->mbr_req_count = 0;
|
||||
for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
|
||||
target->gpt_req[i] = NULL;
|
||||
target->gpt_req_count = 0;
|
||||
target->gpt_req_flags = 0;
|
||||
target->gpt_part_start = 0;
|
||||
target->gpt_backup_end = 0;
|
||||
target->gpt_backup_size = 0;
|
||||
|
@ -828,6 +828,8 @@ struct ecma119_image
|
||||
int apm_req_count;
|
||||
/* 512 by default. May be changed to 2048 before writer thread starts. */
|
||||
int apm_block_size;
|
||||
/* bit1= Do not fill gaps in Apple Partition Map */
|
||||
int apm_req_flags;
|
||||
|
||||
/* MBR partition table description. To be composed during IsoImageWriter
|
||||
method ->compute_data_blocks() by calling iso_register_mbr_entry().
|
||||
@ -845,6 +847,8 @@ struct ecma119_image
|
||||
*/
|
||||
struct iso_gpt_partition_request *gpt_req[ISO_GPT_ENTRIES_MAX];
|
||||
int gpt_req_count;
|
||||
/* bit0= GPT partitions may overlap */
|
||||
int gpt_req_flags;
|
||||
|
||||
char *efi_boot_partition;
|
||||
uint32_t efi_boot_part_size;
|
||||
|
@ -3424,47 +3424,52 @@ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
|
||||
* @param options
|
||||
* bitmask style flag. The following values are defined:
|
||||
*
|
||||
* bit 0 -> 1 to patch the boot info table of the boot image.
|
||||
* 1 does the same as mkisofs option -boot-info-table.
|
||||
* Needed for ISOLINUX or GRUB boot images with platform ID 0.
|
||||
* The table is located at byte 8 of the boot image file.
|
||||
* Its size is 56 bytes.
|
||||
* The original boot image file on disk will not be modified.
|
||||
* bit0= Patch the boot info table of the boot image.
|
||||
* This does the same as mkisofs option -boot-info-table.
|
||||
* Needed for ISOLINUX or GRUB boot images with platform ID 0.
|
||||
* The table is located at byte 8 of the boot image file.
|
||||
* Its size is 56 bytes.
|
||||
* The original boot image file on disk will not be modified.
|
||||
*
|
||||
* One may use el_torito_seems_boot_info_table() for a
|
||||
* qualified guess whether a boot info table is present in
|
||||
* the boot image. If the result is 1 then it should get bit0
|
||||
* set if its content gets copied to a new LBA.
|
||||
* One may use el_torito_seems_boot_info_table() for a
|
||||
* qualified guess whether a boot info table is present in
|
||||
* the boot image. If the result is 1 then it should get bit0
|
||||
* set if its content gets copied to a new LBA.
|
||||
*
|
||||
* bit 1 -> 1 to generate a ISOLINUX isohybrid image with MBR.
|
||||
* ----------------------------------------------------------
|
||||
* @deprecated since 31 Mar 2010:
|
||||
* The author of syslinux, H. Peter Anvin requested that this
|
||||
* feature shall not be used any more. He intends to cease
|
||||
* support for the MBR template that is included in libisofs.
|
||||
* ----------------------------------------------------------
|
||||
* A hybrid image is a boot image that boots from either
|
||||
* CD/DVD media or from disk-like media, e.g. USB stick.
|
||||
* For that you need isolinux.bin from SYSLINUX 3.72 or later.
|
||||
* IMPORTANT: The application has to take care that the image
|
||||
* on media gets padded up to the next full MB.
|
||||
>>> unless a GPT gets created
|
||||
|
||||
* >>> *** Under construction. *** Do not use yet:
|
||||
* >>> bit2-7= Mentioning in isohybrid GPT
|
||||
* >>> 0= do not mention in GPT
|
||||
* >>> 1= mention as EFI partition
|
||||
* >>> @since 1.2.4
|
||||
* >>> 2= Mention as HFS+ partition
|
||||
* >>> @since 1.2.4
|
||||
* >>> Primary GPT and backup GPT get written if at least one
|
||||
* >>> ElToritoBootImage shall be mentioned
|
||||
* >>> bit8= Mention in isohybrid Apple partition map
|
||||
* >>> APM get written if at least one ElToritoBootImage shall be
|
||||
* >>> mentioned. The ISOLINUX MBR must look suitable or else an error
|
||||
* >>> event will happen at image generation time.
|
||||
* >>> @since 1.2.4
|
||||
|
||||
* bit1= Generate a ISOLINUX isohybrid image with MBR.
|
||||
* ----------------------------------------------------------
|
||||
* @deprecated since 31 Mar 2010:
|
||||
* The author of syslinux, H. Peter Anvin requested that this
|
||||
* feature shall not be used any more. He intends to cease
|
||||
* support for the MBR template that is included in libisofs.
|
||||
* ----------------------------------------------------------
|
||||
* A hybrid image is a boot image that boots from either
|
||||
* CD/DVD media or from disk-like media, e.g. USB stick.
|
||||
* For that you need isolinux.bin from SYSLINUX 3.72 or later.
|
||||
* IMPORTANT: The application has to take care that the image
|
||||
* on media gets padded up to the next full MB.
|
||||
* Under seiveral circumstances it might get aligned
|
||||
* automatically. But there is no warranty.
|
||||
* bit2-7= Mentioning in isohybrid GPT
|
||||
* 0= Do not mention in GPT
|
||||
* 1= Mention as Basic Data partition.
|
||||
* This cannot be combined with GPT partitions as of
|
||||
* iso_write_opts_set_efi_bootp()
|
||||
* >>> ts B20620 : and not with iso_write_opts_set_hfsplus()
|
||||
* >>> if it produces GPT entries
|
||||
* @since 1.2.4
|
||||
* 2= Mention as HFS+ partition.
|
||||
* This cannot be combined with HFS+ production by
|
||||
* iso_write_opts_set_hfsplus().
|
||||
* @since 1.2.4
|
||||
* Primary GPT and backup GPT get written if at least one
|
||||
* ElToritoBootImage shall be mentioned
|
||||
* @since 1.2.4
|
||||
* bit8= Mention in isohybrid Apple partition map
|
||||
* APM get written if at least one ElToritoBootImage shall be
|
||||
* mentioned. The ISOLINUX MBR must look suitable or else an error
|
||||
* event will happen at image generation time.
|
||||
* @since 1.2.4
|
||||
* @param flag
|
||||
* Reserved for future usage, set to 0.
|
||||
* @return
|
||||
|
@ -358,7 +358,10 @@ Main:
|
||||
*/
|
||||
|
||||
|
||||
/* >>> ISOHYBRID : mention the new stuff learned from mjg and isohybrid.c */
|
||||
/* The new stuff about GPT and APM which was learned from Matthew Garret
|
||||
and isohybrid.c is described in doc/boot_sectord.txt chapter
|
||||
"SYSLINUX isohybrid for MBR, UEFI and x86-Mac"
|
||||
*/
|
||||
|
||||
|
||||
static
|
||||
@ -385,11 +388,29 @@ int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
|
||||
}
|
||||
|
||||
|
||||
/* Find out whether GPT and APM are desired */
|
||||
static int assess_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
||||
int *apm_count)
|
||||
/* Find out whether GPT and APM are desired
|
||||
flag bit0 = register APM and GPT requests in Ecma119Image
|
||||
*/
|
||||
int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
||||
int *apm_count, int flag)
|
||||
{
|
||||
int i, ilx_opts;
|
||||
int i, ilx_opts, j, ret;
|
||||
uint32_t block_count;
|
||||
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 uint8_t basic_data_uuid[16] = {
|
||||
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
|
||||
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
|
||||
};
|
||||
static uint8_t hfs_uuid[16] = {
|
||||
0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
|
||||
0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
|
||||
};
|
||||
uint8_t *uuid;
|
||||
static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
|
||||
|
||||
*gpt_count = 0;
|
||||
*apm_count = 0;
|
||||
|
||||
for (i = 0; i < t->catalog->num_bootimages; i++) {
|
||||
ilx_opts = t->catalog->bootimages[i]->isolinux_options;
|
||||
@ -397,15 +418,57 @@ static int assess_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
||||
if (*gpt_count < 128)
|
||||
gpt_idx[*gpt_count]= i;
|
||||
(*gpt_count)++;
|
||||
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||
/* Register GPT entry */
|
||||
memset(gpt_name, 0, 72);
|
||||
sprintf((char *) gpt_name, "ISOHybrid%d", *gpt_count);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
if (((ilx_opts >> 2) & 63) == 2)
|
||||
uuid = hfs_uuid;
|
||||
else
|
||||
uuid = basic_data_uuid;
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
ret = iso_quick_gpt_entry(
|
||||
t, t->bootsrc[i]->sections[0].block,
|
||||
block_count, uuid, zero_uuid, gpt_flags,
|
||||
(uint8_t *) gpt_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (ilx_opts & 256)
|
||||
if (ilx_opts & 256) {
|
||||
(*apm_count)++;
|
||||
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||
/* Register APM entry */
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
ret = iso_quick_apm_entry(t, t->bootsrc[i]->sections[0].block,
|
||||
block_count, "EFI", "Apple_HFS");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Prevent gap filling */
|
||||
t->apm_req_flags |= 2;
|
||||
t->apm_block_size = 2048;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*apm_count > 6) {
|
||||
iso_msgs_submit(0,
|
||||
"Too many entries desired for Apple Partition Map. (max 6)",
|
||||
0, "FAILURE", 0);
|
||||
return ISO_BOOT_TOO_MANY_APM;
|
||||
if ((flag & 1) && *gpt_count > 0) {
|
||||
/* Register overall GPT partition */
|
||||
memset(gpt_name, 0, 72);
|
||||
sprintf((char *) gpt_name, "ISOHybrid");
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
/* Let it be open ended. iso_write_gpt() will truncate it as needed. */
|
||||
block_count = 0xffffffff;
|
||||
ret = iso_quick_gpt_entry(t, (uint32_t) 0, block_count,
|
||||
basic_data_uuid, zero_uuid, gpt_flags,
|
||||
(uint8_t *) gpt_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Remove ban on GPT overlapping */
|
||||
t->gpt_req_flags |= 1;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -432,6 +495,12 @@ static int insert_apm_head(uint8_t *buf, int apm_count)
|
||||
for (i = 0; i < 32; i++)
|
||||
if(buf[i] != apm_mbr_start[i])
|
||||
break;
|
||||
if (i < 32) {
|
||||
/* Maybe it is already patched by apm_head ? */
|
||||
for (i = 0; i < 32; i++)
|
||||
if(buf[i] != apm_head[i])
|
||||
break;
|
||||
}
|
||||
if (i < 32) {
|
||||
iso_msgs_submit(0,
|
||||
"MBR template file seems not prepared for Apple Partition Map.",
|
||||
@ -445,7 +514,7 @@ static int insert_apm_head(uint8_t *buf, int apm_count)
|
||||
}
|
||||
|
||||
|
||||
/* Describe the first three GPT boot images as MBR partitions */
|
||||
/* Describe GPT boot images as MBR partitions */
|
||||
static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
||||
int gpt_idx[128], int *gpt_cursor)
|
||||
{
|
||||
@ -480,55 +549,6 @@ static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
||||
}
|
||||
|
||||
|
||||
#ifdef NIX
|
||||
|
||||
static int write_gpt_array(Ecma119Image *t, char *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
|
||||
};
|
||||
static uint8_t hfs_uuid[16] = {
|
||||
0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
|
||||
0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
|
||||
};
|
||||
uint8_t *uuid;
|
||||
int i, ilx_opts;
|
||||
off_t start_lba, end_lba;
|
||||
|
||||
/* >>> 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])
|
||||
*/;
|
||||
|
||||
/* >>> Each marked boot image gets its entry */;
|
||||
for (i= 0; i < t->catalog->num_bootimages; i++) {
|
||||
ilx_opts= (t->catalog->bootimages[i]->isolinux_options >> 2) & 63;
|
||||
if (ilx_opts == 1)
|
||||
uuid = basic_data_uuid;
|
||||
else if (ilx_opts == 1)
|
||||
uuid = hfs_uuid;
|
||||
else
|
||||
continue;
|
||||
|
||||
/* >>> iso_quick_gpt_entry() */
|
||||
|
||||
}
|
||||
|
||||
/* >>> */;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* NIX */
|
||||
|
||||
|
||||
/*
|
||||
* @param flag bit0= make own random MBR Id from current time
|
||||
*/
|
||||
@ -539,7 +559,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 = 0, part_start, max_gpt_entries;
|
||||
uint32_t boot_lba, mbr_id;
|
||||
int head_count, sector_count, ret;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
|
||||
/* For generating a weak random number */
|
||||
@ -553,25 +573,22 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
||||
head_count = t->partition_heads_per_cyl;
|
||||
sector_count = t->partition_secs_per_head;
|
||||
|
||||
ret = assess_gpt_apm(t, &gpt_count, gpt_idx, &apm_count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = insert_apm_head(buf, apm_count);
|
||||
ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* The rest of APM has already been written by iso_write_apm().
|
||||
But the isohybrid APM head differs from the hfsplus_writer APM head.
|
||||
*/
|
||||
ret = insert_apm_head(buf, apm_count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Padding of image_size to a multiple of sector_count*head_count
|
||||
happens already at compute time and is implemented by
|
||||
an appropriate increase of Ecma119Image->tail_blocks.
|
||||
*/
|
||||
|
||||
if (gpt_count) {
|
||||
|
||||
/* >>> ISOHYBRID : need to make sure that backup GPT fits into tail */;
|
||||
|
||||
}
|
||||
|
||||
wpt = (char *) buf + 432;
|
||||
|
||||
/* write qword boot_lba # Offset 432
|
||||
@ -636,27 +653,6 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
||||
*/
|
||||
lsb_to_buf(&wpt, 0xaa55, 16, 0);
|
||||
|
||||
if (gpt_count) {
|
||||
|
||||
/* >>> 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 = 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;
|
||||
}
|
||||
|
||||
if (apm_count) {
|
||||
|
||||
/* >>> ISOHYBRID : write APM entry blocks (2K) */;
|
||||
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,13 @@ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
|
||||
int part_offset, int part_number, int fs_type,
|
||||
uint8_t *buf, int flag);
|
||||
|
||||
/* Find out whether GPT and APM are desired by isohybrid
|
||||
flag bit0 = register APM and GPT requests in Ecma119Image
|
||||
*/
|
||||
int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
||||
int *apm_count, int flag);
|
||||
|
||||
|
||||
static int precompute_gpt(Ecma119Image *t);
|
||||
|
||||
|
||||
@ -804,6 +811,12 @@ int cmp_partition_request(const void *f1, const void *f2)
|
||||
return -1;
|
||||
if (r1->start_block > r2->start_block)
|
||||
return 1;
|
||||
|
||||
/* In case of overlapping the largest partition shall be first */
|
||||
if (r1->block_count > r2->block_count)
|
||||
return -1;
|
||||
if (r1->block_count < r2->block_count)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -919,7 +932,11 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
|
||||
"Program error: APM partitions %d and %d overlap by %lu blocks",
|
||||
i - 1, i, part_end - goal);
|
||||
return ISO_BOOT_APM_OVERLAP;
|
||||
}
|
||||
}
|
||||
|
||||
if (t->apm_req_flags & 2) /* Do not fill gaps */
|
||||
continue;
|
||||
|
||||
if (part_end < goal || i == up_to - 1) { /* Always add a final entry */
|
||||
sprintf(gap_name, "Gap%d", gap_counter);
|
||||
gap_counter++;
|
||||
@ -931,8 +948,9 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
|
||||
}
|
||||
|
||||
/* 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_partition_request);
|
||||
if (!(t->apm_req_flags & 2)) /* No gaps were filled */
|
||||
qsort(t->apm_req, t->apm_req_count,
|
||||
sizeof(struct iso_apm_partition_request *), cmp_partition_request);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -968,7 +986,10 @@ static int rectify_apm(Ecma119Image *t)
|
||||
}
|
||||
|
||||
|
||||
static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
/* flag bit0= do not write Block0
|
||||
*/
|
||||
static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
|
||||
int flag)
|
||||
{
|
||||
int i, ret;
|
||||
/* This is a micro mick-up of an APM Block0
|
||||
@ -1001,15 +1022,18 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
if (t->apm_req_count <= 0)
|
||||
return 2;
|
||||
|
||||
/* Adjust last partition to img_size. This size was not known when the
|
||||
number of APM partitions was determined.
|
||||
*/
|
||||
t->apm_req[t->apm_req_count - 1]->block_count =
|
||||
img_blocks - t->apm_req[t->apm_req_count - 1]->start_block;
|
||||
/* If it is still empty, remove it */
|
||||
if(t->apm_req[t->apm_req_count - 1]->block_count == 0) {
|
||||
free(t->apm_req[t->apm_req_count - 1]);
|
||||
t->apm_req_count--;
|
||||
if (!(t->apm_req_flags & 2)) {
|
||||
/* Gaps have been filled. Care for the final one */
|
||||
/* Adjust last partition to img_size. This size was not known when the
|
||||
number of APM partitions was determined.
|
||||
*/
|
||||
t->apm_req[t->apm_req_count - 1]->block_count =
|
||||
img_blocks - t->apm_req[t->apm_req_count - 1]->start_block;
|
||||
/* If it is still empty, remove it */
|
||||
if(t->apm_req[t->apm_req_count - 1]->block_count == 0) {
|
||||
free(t->apm_req[t->apm_req_count - 1]);
|
||||
t->apm_req_count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* If block size is larger than 512, then not all 63 entries will fit */
|
||||
@ -1020,10 +1044,14 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
t->apm_req[0]->start_block = 1;
|
||||
t->apm_req[0]->block_count = t->apm_req_count;
|
||||
|
||||
/* Write APM block 0. Very sparse, not to overwrite much of possible MBR.*/
|
||||
memcpy(buf, block0_template, 8);
|
||||
buf[2]= (t->apm_block_size >> 8) & 0xff;
|
||||
buf[3]= 0;
|
||||
if (!(flag & 1)) {
|
||||
/* Write APM block 0. Very sparse, not to overwrite much of
|
||||
possible MBR.
|
||||
*/
|
||||
memcpy(buf, block0_template, 8);
|
||||
buf[2]= (t->apm_block_size >> 8) & 0xff;
|
||||
buf[3]= 0;
|
||||
}
|
||||
|
||||
/* Write APM Block 1 to t->apm_req_count */
|
||||
for (i = 0; i < t->apm_req_count; i++) {
|
||||
@ -1217,7 +1245,7 @@ int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
|
||||
|
||||
|
||||
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
|
||||
static void poor_man_s_utf_16le(uint8_t gap_name[72])
|
||||
void iso_ascii_utf_16le(uint8_t gap_name[72])
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1235,7 +1263,7 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
|
||||
};
|
||||
|
||||
uint32_t p_arr_crc = 0, part_end, goal;
|
||||
uint32_t p_arr_crc = 0, part_end, goal, next_end;
|
||||
uint64_t start_lba, end_lba;
|
||||
int ret, i, gap_counter = 0, up_to;
|
||||
struct iso_gpt_partition_request *req;
|
||||
@ -1251,29 +1279,35 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
|
||||
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;
|
||||
goal = 0;
|
||||
part_end = 0;
|
||||
for (i = 0; i < up_to; i++) {
|
||||
if (i < up_to - 1)
|
||||
if (i < up_to - 1) {
|
||||
goal = t->gpt_req[i]->start_block;
|
||||
else
|
||||
} else {
|
||||
goal = img_blocks;
|
||||
}
|
||||
if (i == 0) {
|
||||
if (goal <= 16)
|
||||
continue;
|
||||
part_end = 16;
|
||||
next_end = 16;
|
||||
} else {
|
||||
part_end = t->gpt_req[i - 1]->start_block +
|
||||
next_end = t->gpt_req[i - 1]->start_block +
|
||||
t->gpt_req[i - 1]->block_count;
|
||||
}
|
||||
if (next_end > part_end)
|
||||
part_end = next_end;
|
||||
if (part_end > goal) {
|
||||
iso_msg_submit(t->image->id, ISO_BOOT_GPT_OVERLAP, 0,
|
||||
if (!(t->gpt_req_flags & 1)) {
|
||||
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) {
|
||||
i - 1, i, part_end - goal);
|
||||
return ISO_BOOT_GPT_OVERLAP;
|
||||
}
|
||||
} else if (part_end < goal) {
|
||||
memset(gpt_name, 0, 72);
|
||||
sprintf((char *) gpt_name, "Gap%d", gap_counter);
|
||||
poor_man_s_utf_16le(gpt_name);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
gap_counter++;
|
||||
ret = iso_quick_gpt_entry(t, part_end, goal - part_end,
|
||||
basic_data_uuid, zero_uuid,
|
||||
@ -1293,7 +1327,10 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *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;
|
||||
end_lba = ((uint64_t) req->start_block) + req->block_count;
|
||||
if (end_lba > t->gpt_backup_end - t->gpt_backup_size)
|
||||
end_lba = t->gpt_backup_end - t->gpt_backup_size;
|
||||
end_lba = end_lba * 4 - 1;
|
||||
iso_write_gpt_entry(t, buf + 512 * t->gpt_part_start + 128 * i,
|
||||
req->type_guid, req->partition_guid,
|
||||
start_lba, end_lba, req->flags, req->name);
|
||||
@ -1314,8 +1351,9 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, 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 first_partition = 1, last_partition = 4;
|
||||
int ret, int_img_blocks, sa_type, i, will_append = 0, do_isohybrid = 0;
|
||||
int first_partition = 1, last_partition = 4, apm_flag, part_type;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0;
|
||||
uint32_t img_blocks;
|
||||
|
||||
if ((t == NULL) || (buf == NULL)) {
|
||||
@ -1372,7 +1410,27 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
>>> A sa_type, that does this, will have to adjust the last APM entry
|
||||
>>> if exactness matters.
|
||||
*/
|
||||
ret = iso_write_apm(t, img_blocks, buf);
|
||||
|
||||
apm_flag = 0;
|
||||
if (sa_type == 0 && (t->system_area_options & 3) == 2) {
|
||||
do_isohybrid = 1;
|
||||
|
||||
/* >>> Coordinate with partprepend writer */
|
||||
/* <<< provisory trap */
|
||||
if (t->mbr_req_count > 0)
|
||||
return ISO_BOOT_MBR_OVERLAP;
|
||||
|
||||
/* If own APM is desired, set flag bit0 to prevent writing of Block0
|
||||
which would interfere with the own Block0 of isohybrid.
|
||||
*/
|
||||
ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (apm_count > 0)
|
||||
apm_flag |= 1;
|
||||
}
|
||||
|
||||
ret = iso_write_apm(t, img_blocks, buf, apm_flag);
|
||||
if (ret < 0) {
|
||||
iso_msg_submit(t->image->id, ret, 0,
|
||||
"Cannot set up Apple Partition Map");
|
||||
@ -1401,7 +1459,7 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
if (ret != ISO_SUCCESS) /* error should never happen */
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
} else if(sa_type == 0 && (t->system_area_options & 2)) {
|
||||
} else if (do_isohybrid) {
|
||||
/* Patch externally provided system area as isohybrid MBR */
|
||||
if (t->catalog == NULL || t->system_area_data == NULL) {
|
||||
/* isohybrid makes only sense together with ISOLINUX boot image
|
||||
@ -1410,20 +1468,17 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
|
||||
return ISO_ISOLINUX_CANT_PATCH;
|
||||
}
|
||||
|
||||
/* >>> ISOHYBRID : need option to set fs_type of MBR partition 1
|
||||
(here it is 0x17) */;
|
||||
if (gpt_count > 0 || apm_count > 0)
|
||||
part_type = 0x00;
|
||||
else
|
||||
part_type = 0x17;
|
||||
|
||||
/* >>> ??? Why is partition_offset 0 here ?
|
||||
It gets adjusted later by iso_offset_partition_start()
|
||||
Would it harm to give the real offset here ?
|
||||
*/;
|
||||
|
||||
/* >>> Coordinate with partprepend writer */
|
||||
/* <<< provisory trap */
|
||||
if (t->mbr_req_count > 0)
|
||||
return ISO_BOOT_MBR_OVERLAP;
|
||||
|
||||
ret = make_isolinux_mbr(&img_blocks, t, 0, 1, 0x17, buf, 1);
|
||||
ret = make_isolinux_mbr(&img_blocks, t, 0, 1, part_type, buf, 1);
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
} else if (sa_type == 1) {
|
||||
@ -1799,15 +1854,41 @@ void iso_random_8byte(Ecma119Image *t, uint8_t result[8])
|
||||
}
|
||||
|
||||
|
||||
/* Probably already called by tail writer */
|
||||
/* Probably already called by tail_writer_compute_data_blocks via
|
||||
iso_align_isohybrid
|
||||
*/
|
||||
static int precompute_gpt(Ecma119Image *t)
|
||||
{
|
||||
uint32_t gpt_part_start;
|
||||
int ret;
|
||||
int ret, sa_type;
|
||||
int gpt_count, gpt_idx[128], apm_count;
|
||||
|
||||
/* Avoid repetition by gpt_tail_writer_compute_data_blocks */
|
||||
t->gpt_is_computed = 1;
|
||||
|
||||
|
||||
/* Assess APM and GPT requests of isohybrid */
|
||||
sa_type = (t->system_area_options >> 2) & 0x3f;
|
||||
if (sa_type == 0 && (t->system_area_options & 3) == 2) {
|
||||
|
||||
/* >>> ISOHYBRID :
|
||||
Shall isohybrid be combinable with other APM and GPT requesters ?
|
||||
*/;
|
||||
/* <<< provisorily: Not compatible */
|
||||
ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (t->gpt_req_count > 0 && gpt_count > 0)
|
||||
return ISO_BOOT_GPT_OVERLAP;
|
||||
if (t->apm_req_count > 0 && apm_count > 0)
|
||||
return ISO_BOOT_APM_OVERLAP;
|
||||
/* Register the GPT and APM partition entries */
|
||||
ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Rectify APM requests early in order to learn the size of GPT.
|
||||
iso_write_apm() relies on this being already done here.
|
||||
So perform even if no GPT is required.
|
||||
@ -1841,7 +1922,7 @@ static int precompute_gpt(Ecma119Image *t)
|
||||
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);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
/*
|
||||
ret = iso_quick_gpt_entry(t, 16, 20, hfs_uuid, zero_uuid,
|
||||
gpt_flags, gpt_name);
|
||||
@ -1854,7 +1935,7 @@ static int precompute_gpt(Ecma119Image *t)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
strcpy((char *) gpt_name, "GPT Test 2");
|
||||
poor_man_s_utf_16le(gpt_name);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
ret = iso_quick_gpt_entry(t, 110, 60, basic_data_uuid, zero_uuid,
|
||||
gpt_flags, gpt_name);
|
||||
if (ret < 0)
|
||||
@ -2058,7 +2139,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
}
|
||||
memset(gpt_name, 0, 72);
|
||||
strcpy((char *) gpt_name, "EFI boot partition");
|
||||
poor_man_s_utf_16le(gpt_name);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
ret = iso_quick_gpt_entry(t, t->curblock, t->efi_boot_part_size,
|
||||
efi_sys_uuid, zero_uuid, gpt_flags, gpt_name);
|
||||
if (ret < 0)
|
||||
@ -2091,7 +2172,7 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
return ret;
|
||||
}
|
||||
if (t->prep_part_size > 0) {
|
||||
ret = iso_quick_mbr_entry(t, t->curblock, t->prep_part_size, 0x42, 0);
|
||||
ret = iso_quick_mbr_entry(t, t->curblock, t->prep_part_size, 0x41, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
t->curblock += t->prep_part_size;
|
||||
|
@ -117,6 +117,8 @@ int iso_quick_mbr_entry(Ecma119Image *t,
|
||||
to the final size of the partition map.
|
||||
If no such entry is requested, then it will be prepended automatically
|
||||
with name "Apple" and type "Apple_partition_map".
|
||||
The requested entries will get sorted and gaps will be filled by more
|
||||
entries.
|
||||
*/
|
||||
struct iso_apm_partition_request {
|
||||
|
||||
@ -174,10 +176,14 @@ void iso_random_8byte(Ecma119Image *t, uint8_t result[8]);
|
||||
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 requested entries will get sorted and gaps will be filled by more
|
||||
entries. Overlapping partitions are allowed only if
|
||||
(Ecma119Image.gpt_req_flags & 1).
|
||||
The block_count will be truncated to the image size before the GPT backup.
|
||||
|
||||
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
|
||||
@ -242,5 +248,7 @@ int partprepend_writer_create(Ecma119Image *target);
|
||||
*/
|
||||
int gpt_tail_writer_create(Ecma119Image *target);
|
||||
|
||||
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
|
||||
void iso_ascii_utf_16le(uint8_t gap_name[72]);
|
||||
|
||||
#endif /* SYSTEM_AREA_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user