1 /* 2 * Copyright (c) 2008 Vreixo Formoso 3 * Copyright (c) 2012 - 2019 Thomas Schmitt 4 * 5 * This file is part of the libisofs project; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License version 2 7 * or later as published by the Free Software Foundation. 8 * See COPYING file for details. 9 */ 10 11 /* 12 * Functions for dealing with the system area, this is, the first 16 blocks 13 * of the image. 14 * 15 * At this time, this is only used for hybrid boot images with isolinux. 16 */ 17 18 #ifndef SYSTEM_AREA_H_ 19 #define SYSTEM_AREA_H_ 20 21 #include "ecma119.h" 22 23 /* 24 * Create a MBR for an isohybrid enabled ISOLINUX boot image. 25 * 26 * It is assumed that the caller has verified the readiness of the boot image 27 * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. 28 * 29 * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. 30 * @param img_blocks The predicted number of 2048 byte blocks in the ISO. 31 * It will get rounded up to full MBs and that many blocks 32 * must really be written as ISO 9660 image. 33 * @param mbr A buffer of at least 512 bytes to take the result which is 34 * to be written as the very beginning of the ISO. 35 * @param flag unused yet, submit 0 36 * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning 37 */ 38 int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); 39 40 /** 41 * Write the system area for the given image to the given buffer. 42 * 43 * @param buf 44 * A buffer with at least 32 K allocated 45 * @param flag 46 * bit0= t->opts->ms_block is not counted in t->total_size 47 * @return 48 * 1 if success, < 0 on error 49 */ 50 int iso_write_system_area(Ecma119Image *t, uint8_t *buf, int flag); 51 52 /** 53 * Adjust t->tail_blocks to the eventual alignment needs of isohybrid booting. 54 */ 55 int iso_align_isohybrid(Ecma119Image *t, int flag); 56 57 58 /** 59 * Read the necessary ELF information from the first MIPS boot file. 60 * See doc/boot_sectors.txt "DEC Boot Block" for "MIPS Little Endian". 61 */ 62 int iso_read_mipsel_elf(Ecma119Image *t, int flag); 63 64 65 /* Compute size and position of appended partitions. 66 */ 67 int iso_compute_append_partitions(Ecma119Image *t, int flag); 68 69 70 /* The parameter struct for production of a single MBR partition entry. 71 See also the description of MBR in doc/boot_sectors.txt. 72 No sorting by start sector and gap filling is done before the System Area 73 gets written. But the entries may get assigned to a desired slot number 74 in the table. 75 Requested entries with block_count == 0 get expanded to the start of 76 the next requested entry resp. to image end, if no entry follows. 77 start_block of a following entry must be at least a high as the sum of 78 start_block and block_count of the previous entry. 79 Empty requested entries will be represented as 16 bytes of 0. 80 */ 81 struct iso_mbr_partition_request { 82 83 /* Always given in blocks of 512 bytes */ 84 uint64_t start_block; 85 86 /* A block count of 0 means that the partition reaches up to the start of 87 the next one. 88 */ 89 uint64_t block_count; 90 91 /* Partition type */ 92 uint8_t type_byte; 93 94 /* 0x80 = bootable */ 95 uint8_t status_byte; 96 97 /* If >= 1 && <= 4 : The partition slot number in MBR. 98 If more than one partition desires the same slot, then an error 99 ISO_BOOT_MBR_COLLISION occurs at registration time. 100 Use iso_mbr_entry_slot_is_free() to detect this in advance. 101 If desired_slot is 0, then the partition entry is put into the 102 lowest MBR slot that is not occupied by an entry with desired_slot > 0 103 or by an entry that was registered before this entry. 104 */ 105 int desired_slot; 106 107 }; 108 109 /* Copies the content of req and registers it in t.mbr_req[]. 110 I.e. after the call the submitted storage of req can be disposed or re-used. 111 Submit 0 as value flag. 112 */ 113 int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array, 114 int *mbr_req_count, 115 struct iso_mbr_partition_request *req, int flag); 116 117 /* Convenience frontend for iso_register_mbr_entry(). 118 name and type are 0-terminated strings, which may get silently truncated. 119 */ 120 int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array, 121 int *mbr_req_count, 122 uint64_t start_block, uint64_t block_count, 123 uint8_t type_byte, uint8_t status_byte, 124 int desired_slot); 125 126 /* Peek in advance whether a desired slot number is already occupied by a 127 registered MBR entry. 128 Parameter slot may be between 0 and 4. 0 always returns "free". 129 Return value is 0 if occupied, 1 if free, and -1 if the slot number is 130 out of range. 131 */ 132 int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array, 133 int mbr_req_count, int slot); 134 135 136 /* The parameter struct for production of a single Apple Partition Map entry. 137 See also the partial APM description in doc/boot_sectors.txt. 138 The list of entries is stored e.g. in Ecma119Image.apm_req, .apm_req_count. 139 The size of a block can be chosen by setting Ecma119Image.apm_block_size. 140 If an entry has start_block <=1, then its block_count will be adjusted 141 to the final size of the partition map. 142 If no such entry is requested, then it will be prepended automatically 143 with name "Apple" and type "Apple_partition_map". 144 The requested entries will get sorted and gaps will be filled by more 145 entries. 146 */ 147 struct iso_apm_partition_request { 148 149 /* Given in blocks of 2 KiB unless (Ecma119Image.apm_req_flags & 4). 150 Written to the ISO image according to Ecma119Image.apm_block_size. 151 */ 152 uint64_t start_block; 153 uint64_t block_count; 154 155 /* All 32 bytes get copied to the system area. 156 Take care to pad up short strings by 0. 157 */ 158 uint8_t name[32]; 159 uint8_t type[32]; 160 161 /* Status of the request object itself: 162 bit0= this is an automatically placed filler partition 163 */ 164 uint32_t req_status; 165 }; 166 167 /* Copies the content of req and registers it in t.apm_req[]. 168 I.e. after the call the submitted storage of req can be disposed or re-used. 169 Submit 0 as value flag. 170 */ 171 int iso_register_apm_entry(struct iso_apm_partition_request **req_array, 172 int *apm_req_count, 173 struct iso_apm_partition_request *req, int flag); 174 175 /* Convenience frontend for iso_register_apm_entry(). 176 name and type are 0-terminated strings, which may get silently truncated. 177 */ 178 int iso_quick_apm_entry(struct iso_apm_partition_request **req_array, 179 int *apm_req_count, 180 uint32_t start_block, uint32_t block_count, 181 char *name, char *type); 182 183 /* These two pseudo-random generators produce byte strings which will 184 surely not duplicate in the first 256 calls. If more calls are necessary 185 in the same process, then one must wait until the output of 186 gettimeofday(2) changes. 187 It is advised to obtain them as late as possible, so that Ecma119Image *t 188 can distinguish itself from other image production setups which might be 189 run on other machines with the same process number at the same time. 190 */ 191 192 /* Produces a GPT disk or partition GUID. 193 Pseudo-random by iso_generate_gpt_guid() if t->gpt_uuid_counter is 0. 194 Else derived reproducibly by counter number from t->gpt_uuid_base. 195 */ 196 void iso_gpt_uuid(Ecma119Image *t, uint8_t uuid[16]); 197 198 /* Mark a given byte string as UUID version 4, RFC 4122. 199 */ 200 void iso_mark_guid_version_4(uint8_t *u); 201 202 /* The parameter struct for production of a single GPT entry. 203 See also the partial GPT description in doc/boot_sectors.txt. 204 The list of entries is stored in Ecma119Image.gpt_req. 205 The GPT header block at byte 0x200 will get produced automatically. 206 The requested entries will get sorted and gaps will be filled by more 207 entries. Overlapping partitions are allowed only if 208 (Ecma119Image.gpt_req_flags & 1). 209 The block_count will be truncated to the image size before the GPT backup. 210 211 The GPT entries will be stored after the Apple Partition Map, if such 212 gets generated too. Both partition descriptions must fit into the 32 KiB 213 of the ISO 9660 System Area. 214 GPT can be combined with APM only if (Ecma119Image.apm_block_size > 512). 215 Otherwise, block 1 of APM and GPT header block would collide. 216 So Ecma119Image.apm_block_size is set automatically to 2048 if at least 217 one GPT entry is requested. (One could try 1024 ...). 218 */ 219 struct iso_gpt_partition_request { 220 221 /* Always given in blocks of 512 bytes. 222 */ 223 uint64_t start_block; 224 uint64_t block_count; 225 226 /* The registered GUID which defines the partition type */ 227 uint8_t type_guid[16]; 228 229 /* An individual GUID which shall be unique to the partition. 230 If the caller submits 0...0 then a (weak) random uuid will be generated. 231 */ 232 uint8_t partition_guid[16]; 233 234 /* bit0= "System Partition" Do not alter, 235 bit2= Legacy BIOS bootable (MBR partition type 0x80) 236 bit60= read-only 237 */ 238 uint64_t flags; 239 240 /* Fill with text encoded as UTF-16LE. 241 All 72 bytes get copied to the system area. 242 Take care to pad up short strings by 0. 243 */ 244 uint8_t name[72]; 245 246 /* Only if read from imported image: Table index of partition (first = 1) 247 */ 248 uint32_t idx; 249 250 /* Status of the request object itself: 251 bit0= this is an automatically placed filler partition 252 */ 253 uint32_t req_status; 254 }; 255 256 /* Copies the content of req and registers it in t.gpt_req[]. 257 I.e. after the call the submitted storage of req can be disposed or re-used. 258 Submit 0 as value flag. 259 */ 260 int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array, 261 int *gpt_req_count, 262 struct iso_gpt_partition_request *req, int flag); 263 264 /* Convenience frontend for iso_register_gpt_entry(). 265 name has to be already encoded as UTF-16LE. 266 */ 267 int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array, 268 int *gpt_req_count, 269 uint64_t start_block, uint64_t block_count, 270 uint8_t type_guid[16], uint8_t partition_guid[16], 271 uint64_t flags, uint8_t name[72]); 272 273 /* Deletes the partition requests for gap filling in GPT and APM. 274 Purpose is to get the request list clean again after a multi-session 275 emulation superblock was created and handed to the application. 276 */ 277 void iso_delete_gpt_apm_fillers(Ecma119Image *target, int flag); 278 279 /* Internal helper that will be used by system_area.c and make_isohybrid_mbr.c 280 */ 281 int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks, 282 uint8_t *buf, uint32_t max_entries, 283 uint32_t part_start, uint32_t p_arr_crc); 284 285 /* The description of a loaded MIPS Big Endian Volume Directory Entry 286 */ 287 struct iso_mips_voldir_entry { 288 char name[9]; 289 uint32_t boot_block; 290 uint32_t boot_bytes; 291 }; 292 293 /* The description of a loaded SUN Disk Label partition */ 294 struct iso_sun_disk_label_entry { 295 int idx; 296 uint16_t id_tag; 297 uint16_t permissions; 298 uint32_t start_cyl; 299 uint32_t num_blocks; 300 }; 301 302 /* Creates the Partition Prepend writer. 303 */ 304 int partprepend_writer_create(Ecma119Image *target); 305 306 /* Creates the Inline Partition Append Writer 307 */ 308 int partappend_writer_create(Ecma119Image *target); 309 310 /* Creates the GPT backup tail writer. 311 */ 312 int gpt_tail_writer_create(Ecma119Image *target); 313 314 /* Not for execution but only to identify the writer by 315 ( writer->write_vol_desc == gpt_tail_writer_write_vol_desc ) 316 */ 317 int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer); 318 319 320 /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */ 321 void iso_ascii_utf_16le(uint8_t gap_name[72]); 322 323 324 /* Parameters of MBR patching for GRUB2 325 Might later become variables in Ecma119Image 326 */ 327 #define Libisofs_grub2_mbr_patch_poS 0x1b0 328 #define Libisofs_grub2_mbr_patch_offsT 4 329 330 /* Parameters of SUN Disk Label patching for GRUB2 331 See API iso_image_set_sparc_core(). 332 */ 333 #define Libisofs_grub2_sparc_patch_adr_poS 0x228 334 #define Libisofs_grub2_sparc_patch_size_poS 0x230 335 336 337 /* Put appended partitions into the writer range 338 */ 339 #define Libisofs_appended_partitions_inlinE yes 340 #ifdef Libisofs_appended_partitions_inlinE 341 /* For padding after appended partitions (and also after backup GPT) 342 */ 343 #define Libisofs_part_align_writeR yes 344 #endif 345 346 #endif /* SYSTEM_AREA_H_ */ 347