| | 75 | uint32_t efi_lba = 0, mac_lba = 0; |
| | 76 | uint16_t efi_count = 0, mac_count = 0; |
| | 77 | uint8_t efi_boot = 0, efi_media = 0, efi_sys = 0; |
| | 78 | |
| | 79 | int apm_parts = 3; |
| | 80 | |
| | 81 | uint8_t afp_header[] = { 0x45, 0x52, 0x08, 0x00, 0x00, 0x00, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
| | 82 | |
| | 83 | uuid_t efi_system_partition = {0xC1, 0x2A, 0x73, 0x28, 0xF8, 0x1F, 0x11, 0xD2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B}; |
| | 84 | uuid_t basic_partition = {0xEB,0xD0,0xA0,0xA2,0xB9,0xE5,0x44,0x33,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7}; |
| | 85 | uuid_t hfs_partition = {0x48, 0x46, 0x53, 0x00, 0x00, 0x00, 0x11, 0xAA, 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC}; |
| | 86 | |
| | 87 | uint32_t crc_tab[256] = |
| | 88 | { |
| | 89 | 0, 0x77073096, 0xEE0E612C, 0x990951BA, |
| | 90 | 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, |
| | 91 | 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, |
| | 92 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, |
| | 93 | 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, |
| | 94 | 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, |
| | 95 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, |
| | 96 | 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, |
| | 97 | 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, |
| | 98 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, |
| | 99 | 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, |
| | 100 | 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, |
| | 101 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, |
| | 102 | 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, |
| | 103 | 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, |
| | 104 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, |
| | 105 | 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, |
| | 106 | 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, |
| | 107 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, |
| | 108 | 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, |
| | 109 | 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, |
| | 110 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, |
| | 111 | 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, |
| | 112 | 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, |
| | 113 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, |
| | 114 | 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, |
| | 115 | 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, |
| | 116 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, |
| | 117 | 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, |
| | 118 | 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, |
| | 119 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, |
| | 120 | 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, |
| | 121 | 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, |
| | 122 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, |
| | 123 | 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, |
| | 124 | 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, |
| | 125 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, |
| | 126 | 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, |
| | 127 | 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, |
| | 128 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, |
| | 129 | 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, |
| | 130 | 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, |
| | 131 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, |
| | 132 | 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, |
| | 133 | 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, |
| | 134 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, |
| | 135 | 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, |
| | 136 | 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, |
| | 137 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, |
| | 138 | 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, |
| | 139 | 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, |
| | 140 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, |
| | 141 | 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, |
| | 142 | 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, |
| | 143 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, |
| | 144 | 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, |
| | 145 | 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, |
| | 146 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, |
| | 147 | 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, |
| | 148 | 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, |
| | 149 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, |
| | 150 | 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, |
| | 151 | 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, |
| | 152 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D |
| | 153 | }; |
| | 154 | |
| | 155 | struct iso_primary_descriptor { |
| | 156 | uint8_t ignore [80]; |
| | 157 | uint32_t size; |
| | 158 | uint8_t ignore2 [44]; |
| | 159 | uint16_t block_size; |
| | 160 | }; |
| | 161 | |
| | 162 | struct gpt_header { |
| | 163 | uint64_t signature; |
| | 164 | uint32_t revision; |
| | 165 | uint32_t headerSize; |
| | 166 | uint32_t headerCRC; |
| | 167 | uint32_t reserved; |
| | 168 | uint64_t currentLBA; |
| | 169 | uint64_t backupLBA; |
| | 170 | uint64_t firstUsableLBA; |
| | 171 | uint64_t lastUsableLBA; |
| | 172 | uuid_t diskGUID; |
| | 173 | uint64_t partitionEntriesLBA; |
| | 174 | uint32_t numParts; |
| | 175 | uint32_t sizeOfPartitionEntries; |
| | 176 | uint32_t partitionEntriesCRC; |
| | 177 | uint8_t reserved2[420]; |
| | 178 | }; |
| | 179 | |
| | 180 | struct gpt_part_header { |
| | 181 | uuid_t partTypeGUID; |
| | 182 | uuid_t partGUID; |
| | 183 | uint64_t firstLBA; |
| | 184 | uint64_t lastLBA; |
| | 185 | uint64_t attributes; |
| | 186 | uint16_t name[36]; |
| | 187 | }; |
| | 188 | |
| | 189 | #define APM_OFFSET 2048 |
| | 190 | |
| | 191 | struct apple_part_header { |
| | 192 | uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */ |
| | 193 | uint16_t res1; |
| | 194 | uint32_t map_count; /* # blocks in partition map */ |
| | 195 | uint32_t start_block; /* absolute starting block # of partition */ |
| | 196 | uint32_t block_count; /* number of blocks in partition */ |
| | 197 | char name[32]; /* partition name */ |
| | 198 | char type[32]; /* string type description */ |
| | 199 | uint32_t data_start; /* rel block # of first data block */ |
| | 200 | uint32_t data_count; /* number of data blocks */ |
| | 201 | uint32_t status; /* partition status bits */ |
| | 202 | uint32_t boot_start; |
| | 203 | uint32_t boot_count; |
| | 204 | uint32_t boot_load; |
| | 205 | uint32_t boot_load2; |
| | 206 | uint32_t boot_entry; |
| | 207 | uint32_t boot_entry2; |
| | 208 | uint32_t boot_cksum; |
| | 209 | char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */ |
| | 210 | uint32_t driver_sig; |
| | 211 | char _padding[372]; |
| | 212 | }; |
| | 674 | uint32_t chksum_crc32 (unsigned char *block, unsigned int length) |
| | 675 | { |
| | 676 | register unsigned long crc; |
| | 677 | unsigned long i; |
| | 678 | |
| | 679 | crc = 0xFFFFFFFF; |
| | 680 | for (i = 0; i < length; i++) |
| | 681 | { |
| | 682 | crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; |
| | 683 | } |
| | 684 | return (crc ^ 0xFFFFFFFF); |
| | 685 | } |
| | 686 | |
| | 687 | void |
| | 688 | reverse_uuid(uuid_t uuid) |
| | 689 | { |
| | 690 | uint8_t t, *p = (uint8_t *)uuid; |
| | 691 | |
| | 692 | t = p[0]; p[0] = p[3]; p[3] = t; |
| | 693 | t = p[1]; p[1] = p[2]; p[2] = t; |
| | 694 | t = p[4]; p[4] = p[5]; p[5] = t; |
| | 695 | t = p[6]; p[6] = p[7]; p[7] = t; |
| | 696 | } |
| | 697 | |
| | 698 | void |
| | 699 | initialise_gpt(uint8_t *gpt, uint32_t current, uint32_t alternate, int primary) |
| | 700 | { |
| | 701 | struct gpt_header *header = (struct gpt_header *)gpt; |
| | 702 | struct gpt_part_header *part; |
| | 703 | int hole = 0; |
| | 704 | int gptsize = 128 / 4 + 2; |
| | 705 | |
| | 706 | if (mac_lba) { |
| | 707 | /* 2048 bytes per partition, plus round to 2048 boundary */ |
| | 708 | hole = (apm_parts * 4) + 2; |
| | 709 | } |
| | 710 | |
| | 711 | if (primary) { |
| | 712 | uuid_generate(disk_uuid); |
| | 713 | reverse_uuid(disk_uuid); |
| | 714 | } |
| | 715 | |
| | 716 | header->signature = lendian_64(0x5452415020494645); |
| | 717 | header->revision = lendian_int(0x010000); |
| | 718 | header->headerSize = lendian_int(0x5c); |
| | 719 | header->currentLBA = lendian_64(current); |
| | 720 | header->backupLBA = lendian_64(alternate); |
| | 721 | header->firstUsableLBA = lendian_64(gptsize + hole); |
| | 722 | header->lastUsableLBA = lendian_64((isostat.st_size + padding)/512 - |
| | 723 | gptsize); |
| | 724 | if (primary) |
| | 725 | header->partitionEntriesLBA = lendian_64(0x02 + hole); |
| | 726 | else |
| | 727 | header->partitionEntriesLBA = lendian_64(current - (128 / 4)); |
| | 728 | header->numParts = lendian_int(0x80); |
| | 729 | header->sizeOfPartitionEntries = lendian_int(0x80); |
| | 730 | memcpy(header->diskGUID, disk_uuid, sizeof(uuid_t)); |
| | 731 | |
| | 732 | if (primary) |
| | 733 | gpt += sizeof(struct gpt_header) + hole * 512; |
| | 734 | else |
| | 735 | gpt -= header->sizeOfPartitionEntries * header->numParts; |
| | 736 | |
| | 737 | part = (struct gpt_part_header *)gpt; |
| | 738 | if (primary) { |
| | 739 | uuid_generate(part_uuid); |
| | 740 | uuid_generate(iso_uuid); |
| | 741 | reverse_uuid(part_uuid); |
| | 742 | reverse_uuid(iso_uuid); |
| | 743 | } |
| | 744 | |
| | 745 | memcpy(part->partGUID, iso_uuid, sizeof(uuid_t)); |
| | 746 | memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t)); |
| | 747 | part->firstLBA = lendian_64(0); |
| | 748 | part->lastLBA = lendian_64(psize); |
| | 749 | memcpy(part->name, "ISOHybrid ISO", 28); |
| | 750 | |
| | 751 | gpt += sizeof(struct gpt_part_header); |
| | 752 | part++; |
| | 753 | |
| | 754 | memcpy(part->partGUID, part_uuid, sizeof(uuid_t)); |
| | 755 | memcpy(part->partTypeGUID, basic_partition, sizeof(uuid_t)); |
| | 756 | part->firstLBA = lendian_64(efi_lba * 4); |
| | 757 | part->lastLBA = lendian_64(part->firstLBA + efi_count - 1); |
| | 758 | memcpy(part->name, "ISOHybrid", 20); |
| | 759 | |
| | 760 | gpt += sizeof(struct gpt_part_header); |
| | 761 | |
| | 762 | if (mac_lba) { |
| | 763 | gpt += sizeof(struct gpt_part_header); |
| | 764 | |
| | 765 | part++; |
| | 766 | |
| | 767 | memcpy(part->partGUID, part_uuid, sizeof(uuid_t)); |
| | 768 | memcpy(part->partTypeGUID, hfs_partition, sizeof(uuid_t)); |
| | 769 | part->firstLBA = lendian_64(mac_lba * 4); |
| | 770 | part->lastLBA = lendian_64(part->firstLBA + mac_count - 1); |
| | 771 | memcpy(part->name, "ISOHybrid", 20); |
| | 772 | |
| | 773 | part--; |
| | 774 | } |
| | 775 | |
| | 776 | part--; |
| | 777 | |
| | 778 | header->partitionEntriesCRC = lendian_int (chksum_crc32((uint8_t *)part, |
| | 779 | header->numParts * header->sizeOfPartitionEntries)); |
| | 780 | |
| | 781 | header->headerCRC = lendian_int(chksum_crc32((uint8_t *)header, |
| | 782 | header->headerSize)); |
| | 783 | } |
| | 784 | |
| | 785 | void |
| | 786 | initialise_apm(uint8_t *gpt, uint32_t start) |
| | 787 | { |
| | 788 | struct apple_part_header *part = (struct apple_part_header *)gpt; |
| | 789 | |
| | 790 | part->signature = bendian_short(0x504d); |
| | 791 | part->map_count = bendian_int(apm_parts); |
| | 792 | part->start_block = bendian_int(1); |
| | 793 | part->block_count = bendian_int(0x10); |
| | 794 | strcpy(part->name, "Apple"); |
| | 795 | strcpy(part->type, "Apple_partition_map"); |
| | 796 | part->data_start = bendian_int(0); |
| | 797 | part->data_count = bendian_int(10); |
| | 798 | part->status = bendian_int(0x03); |
| | 799 | |
| | 800 | part = (struct apple_part_header *)(gpt + 2048); |
| | 801 | |
| | 802 | part->signature = bendian_short(0x504d); |
| | 803 | part->map_count = bendian_int(3); |
| | 804 | part->start_block = bendian_int(efi_lba); |
| | 805 | part->block_count = bendian_int(efi_count); |
| | 806 | strcpy(part->name, "EFI"); |
| | 807 | strcpy(part->type, "Apple_HFS"); |
| | 808 | part->data_start = bendian_int(0); |
| | 809 | part->data_count = bendian_int(efi_count); |
| | 810 | part->status = bendian_int(0x33); |
| | 811 | |
| | 812 | part = (struct apple_part_header *)(gpt + 4096); |
| | 813 | |
| | 814 | if (mac_lba) |
| | 815 | { |
| | 816 | part->signature = bendian_short(0x504d); |
| | 817 | part->map_count = bendian_int(3); |
| | 818 | part->start_block = bendian_int(mac_lba); |
| | 819 | part->block_count = bendian_int(mac_count); |
| | 820 | strcpy(part->name, "EFI"); |
| | 821 | strcpy(part->type, "Apple_HFS"); |
| | 822 | part->data_start = bendian_int(0); |
| | 823 | part->data_count = bendian_int(mac_count); |
| | 824 | part->status = bendian_int(0x33); |
| | 825 | } else { |
| | 826 | part->signature = bendian_short(0x504d); |
| | 827 | part->map_count = bendian_int(3); |
| | 828 | part->start_block = bendian_int((start/2048) + 10); |
| | 829 | part->block_count = bendian_int(efi_lba - start/2048 - 10); |
| | 830 | strcpy(part->name, "ISO"); |
| | 831 | strcpy(part->type, "Apple_Free"); |
| | 832 | part->data_start = bendian_int(0); |
| | 833 | part->data_count = bendian_int(efi_lba - start/2048 - 10); |
| | 834 | part->status = bendian_int(0x01); |
| | 835 | } |
| | 836 | } |
| | 837 | |