xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

system_area.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Vreixo Formoso
3  * Copyright (c) 2010 - 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 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14 
15 #include "libisofs.h"
16 #include "system_area.h"
17 #include "eltorito.h"
18 #include "filesrc.h"
19 #include "ecma119_tree.h"
20 #include "image.h"
21 #include "messages.h"
22 #include "ecma119.h"
23 #include "writer.h"
24 
25 #include <string.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 
32 /* for gettimeofday() */
33 #include <sys/time.h>
34 
35 /* >>> Need ./configure test for uuid_generate() which checks for:
36  uuid_t, uuid_generate, the need for -luuid
37 */
38 /*
39 #define Libisofs_with_uuid_generatE 1
40 */
41 #ifdef Libisofs_with_uuid_generatE
42 #include <uuid/uuid.h>
43 #endif
44 
45 /* O_BINARY is needed for Cygwin but undefined elsewhere */
46 #ifndef O_BINARY
47 #define O_BINARY 0
48 #endif
49 
50 
51 /*
52  * Create a MBR for an isohybrid enabled ISOLINUX boot image.
53  * See libisofs/make_isohybrid_mbr.c
54  * Deprecated.
55  */
56 int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag);
57 
58 /*
59  * The New ISOLINUX MBR Producer.
60  * Be cautious with changing parameters. Only few combinations are tested.
61  *
62  */
63 int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
64  int part_offset, int part_number, int fs_type,
65  uint8_t *buf, int flag);
66 
67 /* Find out whether GPT and APM are desired by isohybrid
68  flag bit0 = register APM and GPT requests in Ecma119Image
69 */
70 int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
71  int *apm_count, int flag);
72 
73 
74 static int precompute_gpt(Ecma119Image *t);
75 
76 
77 /*
78  * @param flag bit0= img_blocks is start address rather than end address:
79  do not subtract 1
80  bit1= img_blocks is counted in 512-byte units rather than 2 KiB
81  */
82 static
83 void iso_compute_cyl_head_sec(uint64_t img_blocks, int hpc, int sph,
84  uint32_t *end_lba, uint32_t *end_sec,
85  uint32_t *end_head, uint32_t *end_cyl, int flag)
86 {
87  uint64_t secs;
88 
89  if(flag & 2)
90  secs = img_blocks;
91  else
92  secs = img_blocks * 4;
93  if (secs > (uint64_t) 0xfffffffc)
94  secs = 0xfffffffc; /* truncate rather than roll over */
95  if (flag & 1)
96  *end_lba = secs; /* first valid 512-lba */
97  else
98  secs = *end_lba = secs - 1; /* last valid 512-lba */
99  *end_cyl = secs / (sph * hpc);
100  secs -= *end_cyl * sph * hpc;
101  *end_head = secs / sph;
102  *end_sec = secs - *end_head * sph + 1; /* Sector count starts by 1 */
103  if (*end_cyl >= 1024) {
104  *end_cyl = 1023;
105  *end_head = hpc - 1;
106  *end_sec = sph;
107  }
108 }
109 
110 /* @param flag bit0= The path contains instructions for the interval reader
111  @return ISO_SUCCESS = ok, partition will be written
112  ISO_SUCCESS + 1 = interval which shall be kept in place
113  else : error code
114 */
115 static int compute_partition_size(Ecma119Image *t, char *disk_path,
116  uint32_t *size, int flag)
117 {
118  int ret, keep;
119  off_t num;
120  struct stat stbuf;
121  struct iso_interval_reader *ivr;
122  off_t byte_count;
123 
124  if (flag & 1) {
125  ret = iso_interval_reader_new(t->image, disk_path,
126  &ivr, &byte_count, 0);
127  if (ret < 0)
128  return ret;
129  *size = (byte_count + BLOCK_SIZE - 1) / BLOCK_SIZE;
130  keep = iso_interval_reader_keep(t, ivr, 0);
132  if (keep < 0)
133  return keep;
134  return ISO_SUCCESS + (keep > 0);
135  }
136 
137  *size = 0;
138  ret = stat(disk_path, &stbuf);
139  if (ret == -1)
140  return ISO_BAD_PARTITION_FILE;
141  if (! S_ISREG(stbuf.st_mode))
142  return ISO_BAD_PARTITION_FILE;
143  num = ((stbuf.st_size + 2047) / 2048);
144  if (num > 0x3fffffff || num == 0)
145  return ISO_BAD_PARTITION_FILE;
146  *size = num;
147  return ISO_SUCCESS;
148 }
149 
150 /* Compute size and position of appended partitions.
151  @param flag bit0= Partitions inside ISO : update t->curblock
152 */
154 {
155  int ret, i, sa_type, cyl_align, cyl_size = 0;
156  int first_partition, last_partition;
157  uint32_t pos, size, add_pos = 0;
158  off_t start_byte, byte_count;
159  char msg[128];
160 
161  sa_type = (t->system_area_options >> 2) & 0x3f;
162  cyl_align = (t->system_area_options >> 8) & 0x3;
163  if (sa_type == 0 && cyl_align == 3) {
165  if (cyl_size % 4)
166  cyl_size = 0;
167  else
168  cyl_size /= 4;
169  }
170 
171 #ifdef Libisofs_appended_partitions_inlinE
172 
173  pos = t->curblock;
174 
175 #else
176 
177  pos = (t->vol_space_size + t->opts->ms_block);
178 
179 #endif
180 
181  iso_tell_max_part_range(t->opts, &first_partition, &last_partition, 0);
182  for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
183  if (t->opts->appended_partitions[i] == NULL)
184  continue;
185  if (t->opts->appended_partitions[i][0] == 0)
186  continue;
187  if (i + 1 > last_partition || i + 1 < first_partition) {
188  sprintf(msg,
189  "Partition number %d of appended partition is out of range [%d - %d]",
190  i + 1, first_partition, last_partition);
191  iso_msgs_submit(0, msg, 0, "FAILURE", 0);
192  return ISO_BAD_PARTITION_NO;
193  }
194 
195  ret = compute_partition_size(t, t->opts->appended_partitions[i], &size,
196  t->opts->appended_part_flags[i]);
197  if (ret < 0)
198  return ret;
199  if (ret == ISO_SUCCESS + 1) {
200  /* Interval from imported_iso in add-on session */
201  t->appended_part_prepad[i] = 0;
203  t->opts->appended_partitions[i],
204  &start_byte, &byte_count, 0);
205  if (ret < 0)
206  return ret;
207  t->appended_part_start[i] = start_byte / 2048;
208  t->appended_part_size[i] = size;
209  t->opts->iso_mbr_part_type = 0;
210  continue;
211  }
212 
213  add_pos = 0;
214  if (sa_type == 3 && (pos % ISO_SUN_CYL_SIZE)) {
215  add_pos = ISO_SUN_CYL_SIZE - (pos % ISO_SUN_CYL_SIZE);
216  } else if (cyl_size > 0 && (pos % cyl_size)) {
217  add_pos = cyl_size - (pos % cyl_size);
218  }
219  t->appended_part_prepad[i] = add_pos;
220  t->appended_part_start[i] = pos + add_pos;
221 
222  if (cyl_size > 0 && (size % cyl_size)) {
223  /* Obey cylinder alignment (missing data will be written as
224  zeros by iso_write_partition_file()) */
225  size += cyl_size - (size % cyl_size);
226  }
227  t->appended_part_size[i] = size;
228  pos += add_pos + size;
229  t->total_size += (((off_t) add_pos) + size) * 2048;
230  if (flag & 1)
231  t->curblock = pos;
232  }
233  return ISO_SUCCESS;
234 }
235 
236 
237 static int mbr_part_slot_is_unused(uint8_t *slot)
238 {
239  int i;
240 
241  for (i = 0; i < 16; i++)
242  if (slot[i] != 0)
243  break;
244  if (i >= 16)
245  return 1;
246  return 0;
247 }
248 
249 
250 /* @param flag
251  bit1= partition_offset and partition_size are counted in
252  blocks of 512 rather than 2048
253  */
254 static int write_mbr_partition_entry(int partition_number, int partition_type,
255  uint64_t partition_offset, uint64_t partition_size,
256  int sph, int hpc, uint8_t *buf, int flag)
257 {
258  uint8_t *wpt;
259  uint32_t end_lba, end_sec, end_head, end_cyl;
260  uint32_t start_lba, start_sec, start_head, start_cyl;
261  uint32_t after_end;
262  int i;
263 
264  after_end = partition_offset + partition_size;
265  iso_compute_cyl_head_sec((uint64_t) partition_offset, hpc, sph,
266  &start_lba, &start_sec, &start_head, &start_cyl,
267  1 | (flag & 2));
268  iso_compute_cyl_head_sec((uint64_t) after_end, hpc, sph,
269  &end_lba, &end_sec, &end_head, &end_cyl,
270  (flag & 2));
271  wpt = buf + 446 + (partition_number - 1) * 16;
272 
273  /* Not bootable */
274  *(wpt++) = 0x00;
275 
276  /* C/H/S of the start */
277  *(wpt++) = start_head;
278  *(wpt++) = start_sec | ((start_cyl & 0x300) >> 2);
279  *(wpt++) = start_cyl & 0xff;
280 
281  /* (partition type) */
282  *(wpt++) = partition_type;
283 
284  /* 3 bytes of C/H/S end */
285  *(wpt++) = end_head;
286  *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2);
287  *(wpt++) = end_cyl & 0xff;
288 
289  /* LBA start in little endian */
290  for (i = 0; i < 4; i++)
291  *(wpt++) = (start_lba >> (8 * i)) & 0xff;
292 
293  /* Number of sectors in partition, little endian */
294  end_lba = end_lba - start_lba + 1;
295  for (i = 0; i < 4; i++)
296  *(wpt++) = (end_lba >> (8 * i)) & 0xff;
297 
298  /* Afaik, partition tables are recognize donly with MBR signature */
299  buf[510] = 0x55;
300  buf[511] = 0xAA;
301 
302  return ISO_SUCCESS;
303 }
304 
305 
306 /* This is the gesture of grub-mkisofs --protective-msdos-label as explained by
307  Vladimir Serbinenko <phcoder@gmail.com>, 2 April 2010, on grub-devel@gnu.org
308  "Currently we use first and not last entry. You need to:
309  1) Zero-fill 446-510
310  2) Put 0x55, 0xAA into 510-512
311  3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd
312  (partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA
313  start in little endian), [LBA end in little endian] at 446-462
314  "
315 
316  "C/H/S end" means the CHS address of the last block in the partition.
317  It seems that not "[LBA end in little endian]" but "number of blocks"
318  should go into bytes 458-461. But with a start lba of 1, this is the
319  same number.
320  See also http://en.wikipedia.org/wiki/Master_boot_record
321 
322  flag bit0= do not write 0x55, 0xAA to 510,511
323  bit1= do not mark partition as bootable
324 */
325 static
326 int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc,
327  uint8_t part_type, uint8_t *buf, int flag)
328 {
329  uint8_t *wpt;
330  uint32_t end_lba, end_sec, end_head, end_cyl;
331  int i;
332 
333  iso_compute_cyl_head_sec((uint64_t) img_blocks, hpc, sph,
334  &end_lba, &end_sec, &end_head, &end_cyl, 0);
335 
336  /* 1) Zero-fill 446-510 */
337  wpt = buf + 446;
338  memset(wpt, 0, 64);
339 
340  if (!(flag & 1)) {
341  /* 2) Put 0x55, 0xAA into 510-512 (actually 510-511) */
342  buf[510] = 0x55;
343  buf[511] = 0xAA;
344  }
345  if ((!(flag & 2)) && part_type != 0xee && part_type != 0xef) {
346  /* 3) Put 0x80 (for bootable partition), */
347  *(wpt++) = 0x80;
348  } else {
349  *(wpt++) = 0;
350  }
351 
352  /* 0, 2, 0 (C/H/S of the start), */
353  *(wpt++) = 0;
354  *(wpt++) = 2;
355  *(wpt++) = 0;
356 
357  /* 0xcd (partition type) */
358  *(wpt++) = part_type;
359 
360  /* [3 bytes of C/H/S end], */
361  *(wpt++) = end_head;
362  *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2);
363  *(wpt++) = end_cyl & 0xff;
364 
365 
366  /* 0x01, 0x00, 0x00, 0x00 (LBA start in little endian), */
367  *(wpt++) = 0x01;
368  *(wpt++) = 0x00;
369  *(wpt++) = 0x00;
370  *(wpt++) = 0x00;
371 
372  /* [LBA end in little endian] */
373  for (i = 0; i < 4; i++)
374  *(wpt++) = (end_lba >> (8 * i)) & 0xff;
375 
376  /* at 446-462 */
377  if (wpt - buf != 462) {
378  fprintf(stderr,
379  "libisofs: program error in make_grub_msdos_label: \"assert 462\"\n");
380  return ISO_ASSERT_FAILURE;
381  }
382  return ISO_SUCCESS;
383 }
384 
385 
386 /* @param flag bit0= zeroize partitions entries 2, 3, 4
387  bit1= UEFI protective MBR: start LBA = 1
388 */
389 static
390 int iso_offset_partition_start(uint32_t img_blocks, int post_part_pad,
391  uint32_t partition_offset,
392  int sph, int hpc, uint8_t *buf, int flag)
393 {
394  uint8_t *wpt;
395  uint32_t end_lba, end_sec, end_head, end_cyl;
396  uint32_t start_lba, start_sec, start_head, start_cyl;
397  uint64_t img_hd_blocks;
398  int i;
399 
400  iso_compute_cyl_head_sec((uint64_t) partition_offset, hpc, sph,
401  &start_lba, &start_sec, &start_head, &start_cyl, 1);
402  img_hd_blocks = ((uint64_t) img_blocks) * 4 - post_part_pad / 512;
403  iso_compute_cyl_head_sec(img_hd_blocks, hpc, sph,
404  &end_lba, &end_sec, &end_head, &end_cyl, 2);
405  if (flag & 2) {
406  start_lba = 1;
407  start_sec = 2;
408  start_head = start_cyl = 0;
409  }
410  wpt = buf + 446;
411 
412  /* Let pass only legal bootability values */
413  if (*wpt != 0 && *wpt != 0x80)
414  (*wpt) = 0;
415  wpt++;
416 
417  /* C/H/S of the start */
418  *(wpt++) = start_head;
419  *(wpt++) = start_sec | ((start_cyl & 0x300) >> 2);
420  *(wpt++) = start_cyl & 0xff;
421 
422  /* (partition type) */
423  wpt++;
424 
425  /* 3 bytes of C/H/S end */
426  *(wpt++) = end_head;
427  *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2);
428  *(wpt++) = end_cyl & 0xff;
429 
430  /* LBA start in little endian */
431  for (i = 0; i < 4; i++)
432  *(wpt++) = (start_lba >> (8 * i)) & 0xff;
433 
434  /* Number of sectors in partition, little endian */
435  end_lba = end_lba - start_lba + 1;
436  for (i = 0; i < 4; i++)
437  *(wpt++) = (end_lba >> (8 * i)) & 0xff;
438 
439  if (wpt - buf != 462) {
440  fprintf(stderr,
441  "libisofs: program error in iso_offset_partition_start: \"assert 462\"\n");
442  return ISO_ASSERT_FAILURE;
443  }
444 
445  if (flag & 1) /* zeroize the other partition entries */
446  memset(wpt, 0, 3 * 16);
447 
448  return ISO_SUCCESS;
449 }
450 
451 
453  IsoNode **iso_node, Ecma119Node **ecma_node,
454  char *purpose, int flag)
455 {
456  int ret;
457 
458  ret = iso_tree_path_to_node(t->image, path, iso_node);
459  if (ret <= 0) {
461  "Cannot find in ISO image: %s '%s'", purpose, path);
462  return ISO_BOOT_FILE_MISSING;
463  }
464  if ((*iso_node)->type != LIBISO_FILE) {
466  "Designated boot file is not a data file: '%s'", path);
468  }
469 
470  *ecma_node= ecma119_search_iso_node(t, *iso_node);
471  if (*ecma_node == NULL) {
473  "Program error: IsoFile has no Ecma119Node: '%s'", path);
474  return ISO_ASSERT_FAILURE;
475  } else {
476  if ((*ecma_node)->type != ECMA119_FILE) {
478  "Program error: Ecma119Node of IsoFile is no ECMA119_FILE: '%s'",
479  path);
480  return ISO_ASSERT_FAILURE;
481  }
482  }
483  return ISO_SUCCESS;
484 }
485 
486 
487 /* This function was implemented according to doc/boot_sectors.txt section
488  "MIPS Volume Header" which was derived by Thomas Schmitt from
489  cdrkit-1.1.10/genisoimage/boot-mips.c by Steve McIntyre which is based
490  on work of Florian Lohoff and Thiemo Seufer who possibly learned from
491  documents of MIPS Computer Systems, Inc. and Silicon Graphics Computer
492  Systems, Inc.
493  This function itself is entirely under copyright (C) 2010 Thomas Schmitt.
494 */
495 static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
496 {
497  char *namept, *name_field;
498  uint32_t num_cyl, idx, blocks, num, checksum;
499  off_t image_size;
500  static uint32_t bps = 512, spt = 32;
501  Ecma119Node *ecma_node;
502  IsoNode *node;
503  IsoStream *stream;
504  off_t file_size;
505  uint32_t file_lba;
506  int ret;
507 
508  /* Bytes 512 to 32767 may come from image or external file */
509  memset(buf, 0, 512);
510 
511  image_size = t->curblock * 2048;
512 
513  /* 0 - 3 | 0x0be5a941 | Magic number */
514  iso_msb(buf, 0x0be5a941, 4);
515 
516  /* 28 - 29 | num_cyl_l | Number of usable cylinder, lower two bytes */
517  num_cyl = (image_size + (bps * spt) - 1) / (bps * spt);
518  iso_msb(buf + 28, num_cyl & 0xffff, 2);
519 
520  /* 32 - 33 | 1 | Number of tracks per cylinder */
521  iso_msb(buf + 32, 1, 2);
522 
523  /* 35 - 35 | num_cyl_h | Number of usable cylinders, high byte */
524  buf[35] = (num_cyl >> 16) & 0xff;
525 
526  /* 38 - 39 | 32 | Sectors per track */
527  iso_msb(buf + 38, spt, 2);
528 
529  /* 40 - 41 | 512 | Bytes per sector */
530  iso_msb(buf + 40, bps, 2);
531 
532  /* 44 - 47 | 0x00000034 | Controller characteristics */
533  iso_msb(buf + 44, 0x00000034, 4);
534 
535  /* 72 - 87 | ========== | Volume Directory Entry 1 */
536  /* 72 - 79 | boot_name | Boot file basename */
537  /* 80 - 83 | boot_block | ISO 9660 LBA of boot file * 4 */
538  /* 84 - 87 | boot_bytes | File length in bytes */
539  /* 88 - 311 | 0 | Volume Directory Entries 2 to 15 */
540 
541  for (idx = 0; (int) idx < t->image->num_mips_boot_files; idx++) {
543  &node, &ecma_node, "MIPS boot file", 0);
544  if (ret < 0)
545  return ret;
546 
547  namept = (char *) iso_node_get_name(node);
548  name_field = (char *) (buf + (72 + 16 * idx));
549  strncpy(name_field, namept, 8);
550 
551  file_lba = ecma_node->info.file->sections[0].block;
552 
553  iso_msb(buf + (72 + 16 * idx) + 8, file_lba * 4, 4);
554 
555  stream = iso_file_get_stream((IsoFile *) node);
556  file_size = iso_stream_get_size(stream);
557 
558  /* genisoimage rounds up to full multiples of 2048.
559  libisofs did this too until 2020, but the arcload mips boot loader
560  throws error if the rounded size is stored here.
561  So now the exact bytecount gets stored.
562  */
563  iso_msb(buf + (72 + 16 * idx) + 12, file_size, 4);
564 
565  }
566 
567  /* 408 - 411 | part_blks | Number of 512 byte blocks in partition */
568  blocks = (image_size + bps - 1) / bps;
569  iso_msb(buf + 408, blocks, 4);
570  /* 416 - 419 | 0 | Partition is volume header */
571  iso_msb(buf + 416, 0, 4);
572 
573  /* 432 - 435 | part_blks | Number of 512 byte blocks in partition */
574  iso_msb(buf + 432, blocks, 4);
575  iso_msb(buf + 444, 6, 4);
576 
577  /* 504 - 507 | head_chk | Volume header checksum
578  The two's complement of bytes 0 to 503 read
579  as big endian unsigned 32 bit:
580  sum(32-bit-words) + head_chk == 0
581  */
582  checksum = 0;
583  for (idx = 0; idx < 504; idx += 4) {
584  num = iso_read_msb(buf + idx, 4);
585  /* Addition modulo a natural number is commutative and associative.
586  Thus the inverse of a sum is the sum of the inverses of the addends.
587  */
588  checksum -= num;
589  }
590  iso_msb(buf + 504, checksum, 4);
591 
592  return ISO_SUCCESS;
593 }
594 
595 
596 /* The following two functions were implemented according to
597  doc/boot_sectors.txt section "MIPS Little Endian" which was derived
598  by Thomas Schmitt from
599  cdrkit-1.1.10/genisoimage/boot-mipsel.c by Steve McIntyre which is based
600  on work of Florian Lohoff and Thiemo Seufer,
601  and from <elf.h> by Free Software Foundation, Inc.
602 
603  Both functions are entirely under copyright (C) 2010 Thomas Schmitt.
604 */
605 
606 /**
607  * Read the necessary ELF information from the first MIPS boot file.
608  * This is done before image writing starts.
609  */
611 {
612  uint32_t phdr_adr, todo, count;
613  int ret;
614  uint8_t *elf_buf = NULL;
615  IsoNode *iso_node;
616  Ecma119Node *ecma_node;
617  IsoStream *stream;
618 
619  if (t->image->num_mips_boot_files <= 0)
620  {ret = ISO_SUCCESS; goto ex;}
621 
622  LIBISO_ALLOC_MEM(elf_buf, uint8_t, 2048);
624  &iso_node, &ecma_node, "MIPS boot file", 0);
625  if (ret < 0)
626  goto ex;
627  stream = iso_file_get_stream((IsoFile *) iso_node);
628 
629  ret = iso_stream_open(stream);
630  if (ret < 0) {
631  iso_msg_submit(t->image->id, ret, 0,
632  "Cannot open designated MIPS boot file '%s'",
633  t->image->mips_boot_file_paths[0]);
634  goto ex;
635  }
636  ret = iso_stream_read(stream, elf_buf, 32);
637  if (ret != 32) {
638 cannot_read:;
639  iso_stream_close(stream);
640  iso_msg_submit(t->image->id, ret, 0,
641  "Cannot read from designated MIPS boot file '%s'",
642  t->image->mips_boot_file_paths[0]);
643  goto ex;
644  }
645 
646 
647  /* 24 - 27 | e_entry | Entry point virtual address */
648  t->mipsel_e_entry = iso_read_lsb(elf_buf + 24, 4);
649 
650  /* 28 - 31 | e_phoff | Program header table file offset */
651  phdr_adr = iso_read_lsb(elf_buf + 28, 4);
652 
653  /* Skip stream up to byte address phdr_adr */
654  todo = phdr_adr - 32;
655  while (todo > 0) {
656  if (todo > 2048)
657  count = 2048;
658  else
659  count = todo;
660  todo -= count;
661  ret = iso_stream_read(stream, elf_buf, count);
662  if (ret != (int) count)
663  goto cannot_read;
664  }
665  ret = iso_stream_read(stream, elf_buf, 20);
666  if (ret != 20)
667  goto cannot_read;
668 
669  /* 4 - 7 | p_offset | Segment file offset */
670  t->mipsel_p_offset = iso_read_lsb(elf_buf + 4, 4);
671 
672  /* 8 - 11 | p_vaddr | Segment virtual address */
673  t->mipsel_p_vaddr = iso_read_lsb(elf_buf + 8, 4);
674 
675  /* 16 - 19 | p_filesz | Segment size in file */
676  t->mipsel_p_filesz = iso_read_lsb(elf_buf + 16, 4);
677 
678  iso_stream_close(stream);
679  ret = ISO_SUCCESS;
680 ex:;
681  LIBISO_FREE_MEM(elf_buf);
682  return ret;
683 }
684 
685 
686 /**
687  * Write DEC Bootblock from previously read ELF parameters.
688  * This is done when image writing has already begun.
689  */
690 static int make_mipsel_boot_block(Ecma119Image *t, uint8_t *buf, int flag)
691 {
692  int ret;
693  uint32_t seg_size, seg_start;
694  IsoNode *iso_node;
695  Ecma119Node *ecma_node;
696 
697  /* Bytes 512 to 32767 may come from image or external file */
698  memset(buf, 0, 512);
699 
700  if (t->image->num_mips_boot_files <= 0)
701  return ISO_SUCCESS;
702 
704  &iso_node, &ecma_node, "MIPS boot file", 0);
705  if (ret < 0)
706  return ret;
707 
708  /* 8 - 11 | 0x0002757a | Magic number */
709  iso_lsb(buf + 8, 0x0002757a, 4);
710 
711  /* 12 - 15 | 1 | Mode 1: Multi extent boot */
712  iso_lsb(buf + 12, 1, 4);
713 
714  /* 16 - 19 | load_adr | Load address */
715  iso_lsb(buf + 16, t->mipsel_p_vaddr, 4);
716 
717  /* 20 - 23 | exec_adr | Execution address */
718  iso_lsb(buf + 20, t->mipsel_e_entry, 4);
719 
720  /* 24 - 27 | seg_size | Segment size in file. */
721  seg_size = (t->mipsel_p_filesz + 511) / 512;
722  iso_lsb(buf + 24, seg_size, 4);
723 
724  /* 28 - 31 | seg_start | Segment file offset */
725  seg_start = ecma_node->info.file->sections[0].block * 4
726  + (t->mipsel_p_offset + 511) / 512;
727  iso_lsb(buf + 28, seg_start, 4);
728 
729  return ISO_SUCCESS;
730 }
731 
732 
733 /* The following two functions were implemented according to
734  doc/boot_sectors.txt section "SUN Disk Label and boot images" which
735  was derived by Thomas Schmitt from
736  cdrtools-2.01.01a77/mkisofs/sunlabel.h
737  cdrtools-2.01.01a77/mkisofs/mkisofs.8
738  by Joerg Schilling
739 
740  Both functions are entirely under copyright (C) 2010 Thomas Schmitt.
741 */
742 
743 /* @parm flag bit0= copy from next lower valid partition table entry
744  */
745 static int write_sun_partition_entry(int partition_number,
746  char *appended_partitions[],
747  uint32_t partition_offset[], uint32_t partition_size[],
748  uint32_t cyl_size, uint8_t *buf, int flag)
749 {
750  uint8_t *wpt;
751  int read_idx, i;
752 
753  if (partition_number < 1 || partition_number > 8)
754  return ISO_ASSERT_FAILURE;
755 
756  /* 142 - 173 | ========== | 8 partition entries of 4 bytes */
757  wpt = buf + 142 + (partition_number - 1) * 4;
758  if (partition_number == 1)
759  iso_msb(wpt, 4, 2); /* 4 = User partition */
760  else
761  iso_msb(wpt, 2, 2); /* 2 = Root partition with boot image */
762  iso_msb(wpt + 2, 0x10, 2); /* Permissions: 0x10 = read-only */
763 
764  /* 444 - 507 | ========== | Partition table */
765  wpt = buf + 444 + (partition_number - 1) * 8;
766  read_idx = partition_number - 1;
767  if (flag & 1) {
768  /* Search next lower valid partition table entry. #1 is default */
769  for (read_idx = partition_number - 2; read_idx > 0; read_idx--)
770  if (appended_partitions[read_idx] != NULL)
771  if (appended_partitions[read_idx][0] != 0)
772  break;
773  }
774  iso_msb(wpt, partition_offset[read_idx] / (uint32_t) ISO_SUN_CYL_SIZE, 4);
775  iso_msb(wpt + 4, partition_size[read_idx] * 4, 4);
776 
777  /* 510 - 511 | checksum | The result of exoring 2-byte words 0 to 254 */
778  buf[510] = buf[511] = 0;
779  for (i = 0; i < 510; i += 2) {
780  buf[510] ^= buf[i];
781  buf[511] ^= buf[i + 1];
782  }
783 
784  return ISO_SUCCESS;
785 }
786 
787 /**
788  * Write SUN Disk Label with ISO in partition 1 and unused 2 to 8
789  */
790 static int make_sun_disk_label(Ecma119Image *t, uint8_t *buf, int flag)
791 {
792  int ret, i, l;
793  uint64_t blk;
794 
795  /* Bytes 512 to 32767 may come from image or external file */
796  memset(buf, 0, 512);
797 
798  /* 0 - 127 | label | ASCII Label */
799  if (t->opts->ascii_disc_label[0]) {
800  for (l = 0; l < 128 && t->opts->ascii_disc_label[l] != 0; l++);
801  if (l > 0)
802  memcpy((char *) buf, t->opts->ascii_disc_label, l);
803  } else {
804  strcpy((char *) buf,
805  "CD-ROM Disc with Sun sparc boot created by libisofs");
806  }
807 
808  /* 128 - 131 | 1 | Layout version */
809  iso_msb(buf + 128, 1, 4);
810 
811  /* 140 - 141 | 8 | Number of partitions */
812  iso_msb(buf + 140, 8, 2);
813 
814  /* 188 - 191 | 0x600ddeee | vtoc sanity */
815  iso_msb(buf + 188, 0x600ddeee, 4);
816 
817  /* 420 - 421 | 350 | Rotations per minute */
818  iso_msb(buf + 420, 350, 2);
819 
820  /* 422 - 423 | 2048 | Number of physical cylinders (fixely 640 MB) */
821  iso_msb(buf + 422, 2048, 2);
822 
823  /* 430 - 431 | 1 | interleave factor */
824  iso_msb(buf + 430, 1, 2);
825 
826  /* 432 - 433 | 2048 | Number of data cylinders (fixely 640 MB) */
827  iso_msb(buf + 432, 2048, 2);
828 
829  /* 436 - 437 | 1 | Number of heads per cylinder (1 cyl = 320 kB)*/
830  iso_msb(buf + 436, 1, 2);
831 
832  /* 438 - 439 | 640 | Number of sectors per head (1 head = 320 kB) */
833  iso_msb(buf + 438, 640, 2);
834 
835  /* 508 - 509 | 0xdabe | Magic Number */
836  iso_msb(buf + 508, 0xdabe, 2);
837 
838  if (t->sparc_core_src != NULL) {
839  /* May be used for grub-sparc. */
840  blk= ((uint64_t) t->sparc_core_src->sections[0].block) *
841  (uint64_t) 2048;
842  for (i = 0; i < 8; i++)
843  buf[Libisofs_grub2_sparc_patch_adr_poS + i] = blk >> ((7 - i) * 8);
845  t->sparc_core_src->sections[0].size, 4);
846  }
847 
848  /* Set partition 1 to describe ISO image and compute checksum */
849  t->appended_part_start[0] = 0;
850  t->appended_part_size[0] = t->curblock;
853  ISO_SUN_CYL_SIZE, buf, 0);
854  if (ret < 0)
855  return ret;
856  return ISO_SUCCESS;
857 }
858 
859 
861  uint32_t *adr, uint32_t *len, int flag)
862 {
863  int ret;
864  IsoNode *iso_node;
865  Ecma119Node *ecma_node;
866  off_t adr64;
867 
869  &iso_node, &ecma_node, "HP-PA PALO boot file", 0);
870  if (ret < 0)
871  return ret;
872  if (iso_node_get_type(iso_node) != LIBISO_FILE) {
874  "HP-PA PALO file is not a data file");
875  return ISO_HPPA_PALO_NOTREG;
876  }
877  adr64 = ((off_t) 2048) * (off_t) ecma_node->info.file->sections[0].block;
878  if (adr64 > 0x7fffffff) {
880  "HP-PA PALO boot address exceeds 2 GB");
881  return ISO_HPPA_PALO_OFLOW;
882  }
883  *adr = adr64;
884  *len = ecma_node->info.file->sections[0].size;
885  return ISO_SUCCESS;
886 }
887 
888 
889 /**
890  * Write HP-PA PALO boot sector. See doc/boot_sectors.txt
891  *
892  * learned from cdrkit-1.1.10/genisoimage/boot-hppa.c
893  * by Steve McIntyre <steve@einval.com>
894  * who states "Heavily inspired by palo"
895  * Public mail conversations with Helge Deller, beginning with
896  * https://lists.debian.org/debian-hppa/2014/01/msg00016.html
897  * http://git.kernel.org/cgit/linux/kernel/git/deller/palo.git/tree/lib/
898  * (especially struct firstblock in common.h and struct partition in part.h)
899  *
900  */
901 static int make_hppa_palo_sector(Ecma119Image *t, uint8_t *buf, int hdrversion,
902  int flag)
903 {
904  int ret;
905  IsoImage *img;
906  uint32_t adr, len;
907 
908  img = t->image;
909  if (img->hppa_cmdline == NULL && img->hppa_bootloader == NULL &&
910  img->hppa_kernel_32 == NULL && img->hppa_kernel_64 == NULL &&
911  img->hppa_ramdisk == NULL)
912  return ISO_SUCCESS;
913  if (img->hppa_cmdline == NULL || img->hppa_bootloader == NULL ||
914  img->hppa_kernel_32 == NULL || img->hppa_kernel_64 == NULL ||
915  img->hppa_ramdisk == NULL) {
917  "Incomplete HP-PA PALO boot parameters");
918  return ISO_HPPA_PALO_INCOMPL;
919  }
920  if (hdrversion == 4) {
921  /* Bytes 256 to 32767 may come from loaded ISO image or external file */
922  memset(buf, 0, 256);
923  } else if(hdrversion == 5) {
924  memset(buf, 0, 512);
925  memset(buf + 1024, 0, 1024);
926  } else {
928  "Unsupported HP-PA PALO header version %d (can do 4 or 5)",
929  hdrversion);
930  return ISO_WRONG_ARG_VALUE;
931  }
932 
933  /* Magic */
934  iso_msb(buf + 0, 0x8000, 2);
935  /* Name of boot loader */
936  memcpy(buf + 2, "PALO", 5);
937  /* Version */
938  buf[7] = hdrversion;
939 
940  /* Byte address and byte count of the "HPPA 32-bit kernel" file
941  */
942  ret = hppa_palo_get_filepar(t, img->hppa_kernel_32, &adr, &len, 0);
943  if (ret < 0)
944  return ret;
945  iso_msb(buf + 8, adr, 4);
946  iso_msb(buf + 12, len, 4);
947 
948  /* Byte address and byte count of the "HPPA ramdisk" file
949  */
950  ret = hppa_palo_get_filepar(t, img->hppa_ramdisk, &adr, &len, 0);
951  if (ret < 0)
952  return ret;
953  iso_msb(buf + 16, adr, 4);
954  iso_msb(buf + 20, len, 4);
955 
956  if (hdrversion == 4) {
957  /* "Command line" */
958  if (strlen(img->hppa_cmdline) > 127) {
960  "HP-PA PALO command line too long");
961  return ISO_HPPA_PALO_CMDLEN;
962  }
963  memcpy(buf + 24, img->hppa_cmdline, strlen(img->hppa_cmdline) + 1);
964  }
965 
966  /* Byte address and byte count of the "HPPA 64-bit kernel" file
967  */
968  ret = hppa_palo_get_filepar(t, img->hppa_kernel_64, &adr, &len, 0);
969  if (ret < 0)
970  return ret;
971  iso_msb(buf + 232, adr, 4);
972  iso_msb(buf + 236, len, 4);
973 
974  /* Byte address and byte count of the "HPPA bootloader" file
975  */
976  ret = hppa_palo_get_filepar(t, img->hppa_bootloader, &adr, &len, 0);
977  if (ret < 0)
978  return ret;
979  iso_msb(buf + 240, adr, 4);
980  iso_msb(buf + 244, len, 4);
981 
982  if (hdrversion == 5) {
983  if (strlen(img->hppa_cmdline) > 1023) {
985  "HP-PA PALO command line too long");
986  return ISO_HPPA_PALO_CMDLEN;
987  }
988  memcpy(buf + 1024, img->hppa_cmdline, strlen(img->hppa_cmdline) + 1);
989  }
990  return ISO_SUCCESS;
991 }
992 
993 
994 /**
995  * Write DEC Alpha boot sector. See doc/boot_sectors.txt
996  *
997  * learned from cdrkit-1.1.10/genisoimage/boot-alpha.c
998  * by Steve McIntyre <steve@einval.com>
999  * who states "Heavily inspired by isomarkboot by David Mosberger in 1996"
1000  *
1001  */
1002 static int make_dec_alpha_sector(Ecma119Image *t, uint8_t *buf, int flag)
1003 {
1004  int ret, i;
1005  IsoImage *img;
1006  IsoNode *iso_node;
1007  Ecma119Node *ecma_node;
1008  uint64_t size, lba, checksum = 0;
1009 
1010  img = t->image;
1011  if (img->alpha_boot_image == NULL)
1012  return ISO_SUCCESS;
1014  &iso_node, &ecma_node, "DEC Alpha boot file", 0);
1015  if (ret < 0)
1016  return ret;
1017  memset(buf, 0, 512);
1018  strcpy((char *) buf, "Linux/Alpha aboot for ISO filesystem.");
1019  lba = ecma_node->info.file->sections[0].block * 4;
1020  size = ecma_node->info.file->sections[0].size / 512 +
1021  !!(ecma_node->info.file->sections[0].size % 512);
1022  iso_lsb(buf + 480, size & 0xffffffff, 4);
1023  iso_lsb(buf + 484, (size >> 32) & 0xffffffff, 4);
1024  iso_lsb(buf + 488, lba & 0xffffffff, 4);
1025  iso_lsb(buf + 492, (lba >> 32) & 0xffffffff, 4);
1026  for (i = 0; i < 63; i++)
1027  checksum += iso_read_lsb64(buf + 8 * i);
1028  iso_lsb(buf + 504, checksum & 0xffffffff, 4);
1029  iso_lsb(buf + 508, (checksum >> 32) & 0xffffffff, 4);
1030  return ISO_SUCCESS;
1031 }
1032 
1033 /* Convenience frontend for iso_register_apm_entry().
1034  name and type are 0-terminated strings.
1035 */
1037  int *apm_req_count,
1038  uint32_t start_block, uint32_t block_count,
1039  char *name, char *type)
1040 {
1041  int ret, l;
1042  struct iso_apm_partition_request *entry;
1043 
1044  entry = calloc(1, sizeof(struct iso_apm_partition_request));
1045  if (entry == NULL)
1046  return ISO_OUT_OF_MEM;
1047  entry->start_block = start_block;
1048  entry->block_count = block_count;
1049  for (l = 0; l < 32 && name[l] != 0; l++);
1050  if (l > 0)
1051  memcpy((char *) entry->name, name, l);
1052  for (l = 0; l < 32 && type[l] != 0; l++);
1053  if (l > 0)
1054  memcpy((char *) entry->type, type, l);
1055  entry->req_status = 0;
1056  ret = iso_register_apm_entry(req_array, apm_req_count, entry, 0);
1057  free(entry);
1058  return ret;
1059 }
1060 
1061 
1062 static int iso_find_gpt_entry(struct iso_gpt_partition_request **req_array,
1063  int gpt_req_count,
1064  uint64_t start_block, uint64_t block_count,
1065  int *index, int flag)
1066 {
1067  struct iso_gpt_partition_request *entry;
1068 
1069  for (*index = 0; *index < gpt_req_count; (*index)++) {
1070  entry = req_array[*index];
1071  if (entry->start_block == start_block &&
1072  entry->block_count == block_count)
1073  return 1;
1074  }
1075  *index = -1;
1076  return 0;
1077 }
1078 
1079 
1080 /* Convenience frontend for iso_register_gpt_entry().
1081  name has to be already encoded as UTF-16LE.
1082 */
1084  int *gpt_req_count,
1085  uint64_t start_block, uint64_t block_count,
1086  uint8_t type_guid[16], uint8_t partition_guid[16],
1087  uint64_t flags, uint8_t name[72])
1088 {
1089  int ret;
1090  struct iso_gpt_partition_request *entry;
1091 
1092  entry = calloc(1, sizeof(struct iso_gpt_partition_request));
1093  if (entry == NULL)
1094  return ISO_OUT_OF_MEM;
1095  entry->start_block = start_block;
1096  entry->block_count = block_count;
1097  memcpy(entry->type_guid, type_guid, 16);
1098  memcpy(entry->partition_guid, partition_guid, 16);
1099  entry->flags = flags;
1100  memcpy(entry->name, name, 72);
1101  entry->req_status = 0;
1102  ret = iso_register_gpt_entry(req_array, gpt_req_count, entry, 0);
1103  free(entry);
1104  return ret;
1105 }
1106 
1107 
1109  int *mbr_req_count,
1110  uint64_t start_block, uint64_t block_count,
1111  uint8_t type_byte, uint8_t status_byte,
1112  int desired_slot)
1113 {
1114  int ret;
1115  struct iso_mbr_partition_request *entry;
1116 
1117  ret = iso_mbr_entry_slot_is_free(req_array, *mbr_req_count, desired_slot);
1118  if (ret < 0)
1119  desired_slot = 0;
1120  else if (ret == 0)
1121  return ISO_BOOT_MBR_COLLISION;
1122 
1123  entry = calloc(1, sizeof(struct iso_mbr_partition_request));
1124  if (entry == NULL)
1125  return ISO_OUT_OF_MEM;
1126  entry->start_block = start_block;
1127  entry->block_count = block_count;
1128  entry->type_byte = type_byte;
1129  entry->status_byte = status_byte;
1130  entry->desired_slot = desired_slot;
1131  ret = iso_register_mbr_entry(req_array, mbr_req_count, entry, 0);
1132  free(entry);
1133  return ret;
1134 }
1135 
1136 
1138  int mbr_req_count, int slot)
1139 {
1140  int i;
1141 
1142  if (slot < 0 || slot > ISO_MBR_ENTRIES_MAX)
1143  return -1;
1144  if (slot == 0)
1145  return 1;
1146  for (i = 0; i < mbr_req_count; i++)
1147  if (req_array[i]->desired_slot == slot)
1148  return 0;
1149  return 1;
1150 }
1151 
1152 
1153 /**
1154  * Compare the block interval positions of two iso_apm_partition_request
1155  */
1156 static
1157 int cmp_partition_request(const void *f1, const void *f2)
1158 {
1159  struct iso_partition_request {
1160  uint64_t start_block;
1161  uint64_t block_count;
1162  } *r1, *r2;
1163 
1164  r1 = *((struct iso_partition_request **) f1);
1165  r2 = *((struct iso_partition_request **) f2);
1166  if (r1->start_block < r2->start_block)
1167  return -1;
1168  if (r1->start_block > r2->start_block)
1169  return 1;
1170 
1171  /* In case of overlapping the largest partition shall be first */
1172  if (r1->block_count > r2->block_count)
1173  return -1;
1174  if (r1->block_count < r2->block_count)
1175  return 1;
1176  return 0;
1177 }
1178 
1179 
1180 /* @param flag bit0= This is the entry in block 1. Its blocks are already in
1181  the desired apm_block_size unit. Set block_fac to 1.
1182  Set flags to 3 rather than 0x13.
1183 */
1184 static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
1185  struct iso_apm_partition_request *req,
1186  uint8_t *buf, int map_entries, int flag)
1187 {
1188  uint8_t *wpt;
1189  uint32_t flags;
1190  int block_fac;
1191 
1192  if ((flag & 1) || (t->apm_req_flags & 4))
1193  block_fac = 1;
1194  else
1195  block_fac = 2048 / apm_block_size;
1196 
1197  memset(buf, 0, apm_block_size);
1198  wpt = buf;
1199 
1200  /* Signature */
1201  wpt[0] = 'P'; wpt[1] = 'M';
1202  wpt+= 2;
1203  /* reserved */
1204  wpt += 2;
1205  /* Number of partition entries */
1206  iso_msb(wpt, (uint32_t) map_entries, 4);
1207  wpt += 4;
1208  /* Physical block start of partition */
1209  iso_msb(wpt, (uint32_t) (req->start_block * block_fac), 4);
1210  wpt += 4;
1211  /* Physical block count of partition */
1212  iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4);
1213  wpt += 4;
1214  /* Partition name */
1215  memcpy(wpt, req->name, 32);
1216  wpt += 32;
1217  /* Type string */
1218  memcpy(wpt, req->type, 32);
1219  wpt += 32;
1220  /* Logical block start */
1221  iso_msb(wpt, (uint32_t) 0, 4);
1222  wpt += 4;
1223  /* Logical block count */
1224  iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4);
1225  wpt += 4;
1226  /* Status flags : bit0= entry is valid , bit1= entry is allocated
1227  bit4= partition is readable , bit5= partition is writable
1228  bit30= automatic mount (legacy Mac)
1229  */
1230  if (flag & 1) {
1231  flags = 3;
1232  } else {
1233  flags = 0x13;
1234  if (strncmp((char *) req->type, "Apple_HFS", 9) == 0 &&
1235  req->type[9] == 0)
1236  flags |= 0x40000000;
1237  }
1238  iso_msb(wpt, flags, 4);
1239  wpt += 4;
1240 
1241  /* boot_block , boot_bytes , processor , reserved : are all 0 */
1242 
1243  return ISO_SUCCESS;
1244 }
1245 
1246 
1247 /* Sort and fill gaps in requested APM */
1248 static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
1249 {
1250  int i, ret, gap_counter = 0, up_to;
1251  uint32_t part_end, goal, block_fac = 1;
1252  char gap_name[33];
1253 
1254  if (t->apm_req_flags & 4) {
1255  if (t->opts->apm_block_size == 0)
1256  t->opts->apm_block_size = 2048;
1257  block_fac = 2048 / t->opts->apm_block_size;
1258  }
1259 
1260  /* Find out whether an entry with start_block <= 1 is requested */
1261  for (i = 0; i < t->apm_req_count; i++) {
1262  if (t->apm_req[i]->start_block <= 1)
1263  break;
1264  }
1265  if (i >= t->apm_req_count) {
1266  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1267  1, 0, "Apple", "Apple_partition_map");
1268  if (ret < 0)
1269  return ret;
1270  }
1271 
1272  qsort(t->apm_req, t->apm_req_count,
1274 
1275  if (t->opts->part_like_isohybrid)
1276  return 1; /* No filling, only sorting */
1277 
1278  /* t->apm_req_count will grow during the loop */
1279  up_to = t->apm_req_count + 1;
1280  for (i = 1; i < up_to; i++) {
1281  if (i < up_to - 1)
1282  goal = (uint32_t) t->apm_req[i]->start_block;
1283  else
1284  goal = img_blocks * block_fac;
1285  if (i == 1) {
1286  /* Description of APM itself */
1287  /* Actual APM size is not yet known. Protection begins at PVD */
1288  part_end = 16 * block_fac;
1289  if (goal < part_end && goal> 1)
1290  part_end = goal;
1291  } else {
1292  part_end = t->apm_req[i - 1]->start_block +
1293  t->apm_req[i - 1]->block_count;
1294  }
1295  if (part_end > goal) {
1297  "Program error: APM partitions %d and %d overlap by %lu blocks",
1298  i - 1, i, part_end - goal);
1299  return ISO_BOOT_APM_OVERLAP;
1300  }
1301 
1302  if (t->apm_req_flags & 2) /* Do not fill gaps */
1303  continue;
1304 
1305  if (part_end < goal || i == up_to - 1) { /* Always add a final entry */
1306  sprintf(gap_name, "Gap%d", gap_counter);
1307  gap_counter++;
1308  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1309  part_end, goal - part_end,
1310  gap_name, "ISO9660_data");
1311  if (ret < 0)
1312  return ret;
1313  /* Mark as automatically placed filler request */
1314  t->apm_req[t->apm_req_count - 1]->req_status |= 1;
1315  }
1316  }
1317 
1318  /* Merge list of gap partitions with list of already sorted entries */
1319  if (!(t->apm_req_flags & 2)) /* No gaps were filled */
1320  qsort(t->apm_req, t->apm_req_count,
1322 
1323  return 1;
1324 }
1325 
1326 
1328 {
1329  int ret;
1330 
1331 #ifdef NIX
1332  /* Disabled */
1333 
1334  /* <<< ts B20526 : Dummy mock-up */
1335  if (t->apm_req_count <= 0) {
1336  /*
1337  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1338  16, 20, "Test1_name_16_20", "Test1_type");
1339  / * >>> Caution: Size 90 causes intentional partition overlap error * /
1340  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1341  30, 90, "BAD_30_90_BAD", "Test1_type");
1342  */
1343  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1344  30, 20, "Test1_name_30_20", "Test1_type");
1345  if (ret < 0)
1346  return ret;
1347  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1348  100, 400, "Test2_name_100_400", "Test2_type");
1349  if (ret < 0)
1350  return ret;
1351  }
1352 #endif /* NIX */
1353 
1354  if (t->apm_req_count == 0)
1355  return 1;
1356 
1357  if (t->gpt_req_count > 0 &&
1358  t->opts->apm_block_size != 2048 && t->apm_req_count > 0) {
1359  iso_msgs_submit(0,
1360  "GPT and APM requested. APM block size would have to be 2048.",
1361  0, "FAILURE", 0);
1362  return ISO_BOOT_APM_GPT_BSIZE;
1363  }
1364  if (t->apm_req_count > 0) {
1365  ret = fill_apm_gaps(t, t->curblock);
1366  if (ret < 0)
1367  return ret;
1368  }
1369  return 1;
1370 }
1371 
1372 
1373 /* flag bit0= do not write Block0
1374 */
1375 static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
1376  int flag)
1377 {
1378  int i, ret;
1379  uint32_t block_fac = 1;
1380  /* This is a micro mock-up of an APM Block0
1381  and also harmless x86 machine code.
1382  */
1383  static uint8_t block0_template[8] = {
1384  0x45, 0x52, 0x02, 0x00, 0xeb, 0x02, 0xff, 0xff
1385  };
1386 
1387  if (t->apm_req_count <= 0)
1388  return 2;
1389 
1390  if (t->opts->apm_block_size == 0) {
1391  /* One cannot be sure that all GPT partitions are registered
1392  already. So it is necessary to choose the block size which is
1393  combinable with GPT but not mountable on Linux.
1394  */
1395  t->opts->apm_block_size = 2048;
1396  }
1397 
1398  if (t->apm_req_flags & 4)
1399  block_fac = 2048 / t->opts->apm_block_size;
1400 
1401  if (!(t->apm_req_flags & 2)) {
1402  /* Gaps have been filled. Care for the final one */
1403  /* Adjust last partition to img_size. This size was not known when the
1404  number of APM partitions was determined.
1405  */
1406  if (img_blocks * block_fac <
1407  t->apm_req[t->apm_req_count - 1]->start_block)
1408  t->apm_req[t->apm_req_count - 1]->block_count = 0;
1409  else
1410  t->apm_req[t->apm_req_count - 1]->block_count =
1411  img_blocks * block_fac -
1412  t->apm_req[t->apm_req_count - 1]->start_block;
1413  /* If it is still empty, remove it */
1414  if(t->apm_req[t->apm_req_count - 1]->block_count == 0) {
1415  free(t->apm_req[t->apm_req_count - 1]);
1416  t->apm_req_count--;
1417  }
1418  }
1419 
1420  /* If block size is larger than 512, then not all 63 entries will fit */
1421  if ((t->apm_req_count + 1) * t->opts->apm_block_size > 32768)
1422  return ISO_BOOT_TOO_MANY_APM;
1423 
1424  /* Block 1 describes the APM itself */
1425  t->apm_req[0]->start_block = 1;
1426  t->apm_req[0]->block_count = t->apm_req_count;
1427 
1428  if (!(flag & 1)) {
1429  /* Write APM block 0. Very sparse, not to overwrite much of
1430  possible MBR.
1431  */
1432  memcpy(buf, block0_template, 8);
1433  buf[2]= (t->opts->apm_block_size >> 8) & 0xff;
1434  buf[3]= 0;
1435  }
1436 
1437  /* Write APM Block 1 to t->apm_req_count */
1438  for (i = 0; i < t->apm_req_count; i++) {
1439  ret = iso_write_apm_entry(t, t->opts->apm_block_size, t->apm_req[i],
1440  buf + (i + 1) * t->opts->apm_block_size, t->apm_req_count,
1441  i == 0);
1442  if (ret < 0)
1443  return ret;
1444  }
1445  return ISO_SUCCESS;
1446 }
1447 
1448 
1449 static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
1450 {
1451  int i, ret, req_of_slot[ISO_MBR_ENTRIES_MAX], q, j;
1452 
1453 #ifdef NIX
1454  /* Disabled */
1455 
1456  /* <<< Dummy mock-up */
1457  if (t->mbr_req_count <= 0) {
1458  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
1459  (uint64_t) 0, (uint64_t) 0, 0xee, 0, 0);
1460  if (ret < 0)
1461  return ret;
1462  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
1463  ((uint64_t) 100) * 4, (uint64_t) 0,
1464  0x0c, 0x80, 1);
1465  if (ret < 0)
1466  return ret;
1467  }
1468 #endif /* NIX */
1469 
1470  if (t->mbr_req_count <= 0)
1471  return 2;
1472 
1473  /* >>> Sort by start block ? */
1474 
1475  /* Adjust partition ends */
1476  for (i = 0; i < t->mbr_req_count; i++) {
1477  if (i > 0) {
1478  if (t->mbr_req[i]->start_block <= t->mbr_req[i - 1]->start_block &&
1479  !(t->mbr_req[i]->block_count == 0 &&
1480  t->mbr_req[i]->start_block ==
1481  t->mbr_req[i - 1]->start_block))
1482  return ISO_BOOT_MBR_OVERLAP;
1483  if (t->mbr_req[i - 1]->start_block +
1484  t->mbr_req[i - 1]->block_count > t->mbr_req[i]->start_block)
1485  return ISO_BOOT_MBR_OVERLAP;
1486  }
1487  if (t->mbr_req[i]->block_count != 0)
1488  continue;
1489  if (i < t->mbr_req_count - 1)
1490  t->mbr_req[i]->block_count = t->mbr_req[i + 1]->start_block -
1491  t->mbr_req[i]->start_block;
1492  else
1493  t->mbr_req[i]->block_count = ((uint64_t) img_blocks) * 4 -
1494  t->mbr_req[i]->start_block;
1495  }
1496 
1497  /* Assign requested entries to slot numbers */
1498  for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++)
1499  req_of_slot[i] = -1;
1500  for (i = 0; i < t->mbr_req_count; i++) {
1501  if (t->mbr_req[i]->desired_slot < 1 ||
1503  continue;
1504  if (req_of_slot[t->mbr_req[i]->desired_slot - 1] >= 0)
1505  return ISO_BOOT_MBR_COLLISION;
1506  req_of_slot[t->mbr_req[i]->desired_slot - 1] = i;
1507  }
1508  for (i = 0; i < t->mbr_req_count; i++) {
1509  if (t->mbr_req[i]->desired_slot > 0)
1510  continue;
1511  for (j = 0; j < ISO_MBR_ENTRIES_MAX; j++)
1512  if (req_of_slot[j] < 0)
1513  break;
1514  if (j >= ISO_MBR_ENTRIES_MAX)
1515  return ISO_BOOT_TOO_MANY_MBR;
1516  req_of_slot[j] = i;
1517  }
1518 
1519  /* Write partition slots */
1520  for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++) {
1521  memset(buf + 446 + i * 16, 0, 16);
1522  q = req_of_slot[i];
1523  if (q < 0)
1524  continue;
1525  if (t->mbr_req[q]->block_count == 0)
1526  continue;
1527  ret = write_mbr_partition_entry(i + 1, (int) t->mbr_req[q]->type_byte,
1528  t->mbr_req[q]->start_block, t->mbr_req[q]->block_count,
1530  buf, 2);
1531  if (ret < 0)
1532  return ret;
1533  buf[446 + i * 16] = t->mbr_req[q]->status_byte;
1534  }
1535  return ISO_SUCCESS;
1536 }
1537 
1538 
1539 static void iso_write_gpt_entry(Ecma119Image *t, uint8_t *buf,
1540  uint8_t type_guid[16], uint8_t part_uuid[16],
1541  uint64_t start_lba, uint64_t end_lba,
1542  uint64_t flags, uint8_t name[72])
1543 {
1544  char *wpt;
1545  int i;
1546 
1547  wpt = (char *) buf;
1548  memcpy(wpt, type_guid, 16);
1549  wpt += 16;
1550  for (i = 0; i < 16; i++)
1551  if (part_uuid[i])
1552  break;
1553  if (i == 16) {
1554  if (!t->gpt_disk_guid_set)
1555  iso_gpt_uuid(t, t->gpt_disk_guid);
1556  t->gpt_disk_guid_set = 1;
1557  iso_gpt_uuid(t, part_uuid);
1558  }
1559  memcpy(wpt, part_uuid, 16);
1560  wpt += 16;
1561  iso_lsb_to_buf(&wpt, start_lba & 0xffffffff, 4, 0);
1562  iso_lsb_to_buf(&wpt, (start_lba >> 32) & 0xffffffff, 4, 0);
1563  iso_lsb_to_buf(&wpt, end_lba & 0xffffffff, 4, 0);
1564  iso_lsb_to_buf(&wpt, (end_lba >> 32) & 0xffffffff, 4, 0);
1565  iso_lsb_to_buf(&wpt, flags & 0xffffffff, 4, 0);
1566  iso_lsb_to_buf(&wpt, (flags >> 32) & 0xffffffff, 4, 0);
1567  memcpy(wpt, name, 72);
1568 }
1569 
1570 
1571 int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
1572  uint8_t *buf, uint32_t max_entries,
1573  uint32_t part_start, uint32_t p_arr_crc)
1574 {
1575  static char *sig = "EFI PART";
1576  static char revision[4] = {0x00, 0x00, 0x01, 0x00};
1577  char *wpt;
1578  uint32_t crc;
1579  off_t back_lba;
1580 
1581  memset(buf, 0, 512);
1582  wpt = (char *) buf;
1583 
1584  /* >>> Make signature adjustable */
1585  memcpy(wpt, sig, 8); /* no trailing 0 */
1586  wpt += 8;
1587 
1588  memcpy(wpt, revision, 4);
1589  wpt += 4;
1590  iso_lsb_to_buf(&wpt, 92, 4, 0);
1591 
1592  /* CRC will be inserted later */
1593  wpt += 4;
1594 
1595  /* reserved */
1596  iso_lsb_to_buf(&wpt, 0, 4, 0);
1597  /* Own LBA low 32 */
1598  iso_lsb_to_buf(&wpt, 1, 4, 0);
1599  /* Own LBA high 32 */
1600  iso_lsb_to_buf(&wpt, 0, 4, 0);
1601 
1602  /* Backup header LBA is 1 hd block before backup GPT area end */
1603  back_lba = t->gpt_backup_end * 4 - 1;
1604  iso_lsb_to_buf(&wpt, (uint32_t) (back_lba & 0xffffffff), 4, 1);
1605  iso_lsb_to_buf(&wpt, (uint32_t) (back_lba >> 32), 4, 1);
1606 
1607  /* First usable LBA for partitions (4 entries per hd block) */
1608  iso_lsb_to_buf(&wpt, part_start + max_entries / 4, 4, 0);
1609  iso_lsb_to_buf(&wpt, 0, 4, 0);
1610 
1611  /* Last usable LBA for partitions is 1 hd block before first backup entry*/
1612  iso_lsb_to_buf(&wpt,
1613  (uint32_t) ((back_lba - max_entries / 4 - 1) & 0xffffffff),
1614  4, 1);
1615  iso_lsb_to_buf(&wpt,
1616  (uint32_t) ((back_lba - max_entries / 4 - 1) >> 32), 4, 1);
1617 
1618  /* Disk GUID */
1619  if (!t->gpt_disk_guid_set)
1620  iso_gpt_uuid(t, t->gpt_disk_guid);
1621  t->gpt_disk_guid_set = 1;
1622  memcpy(wpt, t->gpt_disk_guid, 16);
1623  wpt += 16;
1624 
1625  /* Partition entries start */
1626  iso_lsb_to_buf(&wpt, part_start, 4, 0);
1627  iso_lsb_to_buf(&wpt, 0, 4, 0);
1628 
1629  /* Number of partition entries */
1630  iso_lsb_to_buf(&wpt, max_entries, 4, 0);
1631 
1632  /* Size of a partition entry */
1633  iso_lsb_to_buf(&wpt, 128, 4, 0);
1634 
1635  /* CRC-32 of the partition array */
1636  iso_lsb_to_buf(&wpt, p_arr_crc, 4, 0);
1637 
1638 
1639  /* <<< Only for a first test */
1640  if (wpt - (char *) buf != 92) {
1641  iso_msgs_submit(0,
1642  "program error : write_gpt_header_block : wpt != 92",
1643  0, "FATAL", 0);
1644  return ISO_ISOLINUX_CANT_PATCH;
1645  }
1646 
1647  /* CRC-32 of this header while head_crc is 0 */
1648  crc = iso_crc32_gpt((unsigned char *) buf, 92, 0);
1649  wpt = ((char *) buf) + 16;
1650  iso_lsb_to_buf(&wpt, crc, 4, 0);
1651 
1652  return ISO_SUCCESS;
1653 }
1654 
1655 
1656 /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
1657 void iso_ascii_utf_16le(uint8_t gap_name[72])
1658 {
1659  int i;
1660 
1661  for (i = strlen((char *) gap_name) - 1; i >= 0; i--) {
1662  gap_name[2 * i] = gap_name[i];
1663  gap_name[2 * i + 1] = 0;
1664  }
1665 }
1666 
1667 
1668 static int intvl_overlap(uint64_t start1, uint64_t end1,
1669  uint64_t start2, uint64_t end2, int second)
1670 {
1671  if (start1 >= start2 && start1 <= end2)
1672  return 1;
1673  if (end1 >= start2 && end1 <= end2)
1674  return 1;
1675  if (!second)
1676  return intvl_overlap(start2, end2, start1, end1, 1);
1677  return 0;
1678 }
1679 
1680 
1681 /* Check APM HFS+ partitions whether they would fit in gaps.
1682  If so, add them as GPT partitions, too.
1683  */
1684 static int iso_copy_apmhfs_to_gpt(Ecma119Image *t, int flag)
1685 {
1686  int a, i, counter = 0, ret;
1687  uint64_t bfac = 4;
1688  static uint8_t hfs_plus_uuid[16] = {
1689  0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
1690  0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
1691  };
1692  static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1693  uint8_t gpt_name[72];
1694  static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
1695 
1696  if ((t->apm_req_flags & 4) && t->opts->apm_block_size / 512 > 0)
1697  bfac = t->opts->apm_block_size / 512;
1698 
1699  for (a = 0; a < t->apm_req_count; a++) {
1700  if (strcmp((char *) t->apm_req[a]->type, "Apple_HFS") != 0)
1701  continue;
1702  for (i = 0; i < t->gpt_req_count; i++)
1703  if (intvl_overlap(t->apm_req[a]->start_block * bfac,
1704  (t->apm_req[a]->start_block +
1705  t->apm_req[a]->block_count - 1) * bfac,
1706  t->gpt_req[i]->start_block,
1707  t->gpt_req[i]->start_block +
1708  t->gpt_req[i]->block_count - 1, 0))
1709  break;
1710  if (i >= t->gpt_req_count) {
1711  memset(gpt_name, 0, 72);
1712  counter++;
1713  if (counter > 1)
1714  sprintf((char *) gpt_name, "HFSPLUS_%d", counter);
1715  else
1716  sprintf((char *) gpt_name, "HFSPLUS");
1717  iso_ascii_utf_16le(gpt_name);
1718  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
1719  t->apm_req[a]->start_block * bfac,
1720  t->apm_req[a]->block_count * bfac,
1721  hfs_plus_uuid, zero_uuid,
1722  gpt_flags, gpt_name);
1723  if (ret < 0)
1724  return ret;
1725  }
1726  }
1727  return 1;
1728 }
1729 
1730 
1731 static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
1732 {
1733  static uint8_t basic_data_uuid[16] = {
1734  0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
1735  0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
1736  };
1737 
1738  uint32_t p_arr_crc = 0;
1739  uint64_t start_lba, end_lba, goal, part_end, next_end, backup_end_lba;
1740  int ret, i, gap_counter = 0, up_to;
1741  struct iso_gpt_partition_request *req;
1742  uint8_t gpt_name[72];
1743  static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1744  static uint8_t *type_guid;
1745  static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
1746 
1747  if (t->gpt_req_count == 0)
1748  return 2;
1749  backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) * 4;
1750 
1751  ret = iso_copy_apmhfs_to_gpt(t, 0);
1752  if (ret <= 0)
1753  return ret;
1754 
1755  /* Sort and fill gaps */
1756  qsort(t->gpt_req, t->gpt_req_count,
1758  /* t->gpt_req_count will grow during the loop */
1759  up_to = t->gpt_req_count + 1;
1760  goal = 0;
1761  part_end = 0;
1762 
1763  if (t->opts->part_like_isohybrid)
1764  up_to = 0; /* No gap filling */
1765 
1766  for (i = 0; i < up_to; i++) {
1767  if (i < up_to - 1) {
1768  goal = t->gpt_req[i]->start_block;
1769  } else {
1770  goal = ((uint64_t) img_blocks) * 4;
1771  if (goal > backup_end_lba)
1772  goal = backup_end_lba;
1773  }
1774  if (i == 0) {
1775  if (goal <= 16 * 4)
1776  continue;
1777  next_end = 16 * 4;
1778  } else {
1779  next_end = t->gpt_req[i - 1]->start_block +
1780  t->gpt_req[i - 1]->block_count;
1781  }
1782  if (next_end > part_end)
1783  part_end = next_end;
1784  if (part_end > goal) {
1785  if (!(t->gpt_req_flags & 1)) {
1787  "Program error: GPT partitions %d and %d overlap by %.f blocks",
1788  i - 1, i, (double) (part_end - goal));
1789  return ISO_BOOT_GPT_OVERLAP;
1790  }
1791  } else if (part_end < goal) {
1792  memset(gpt_name, 0, 72);
1793  type_guid = basic_data_uuid;
1794  if (goal == t->vol_space_size * (uint64_t) 4 &&
1795  part_end == t->opts->partition_offset * (uint64_t) 4) {
1796  sprintf((char *) gpt_name, "ISO9660");
1797  if (t->opts->iso_gpt_flag & 1)
1799  } else {
1800  sprintf((char *) gpt_name, "Gap%d", gap_counter);
1801  }
1802  iso_ascii_utf_16le(gpt_name);
1803  gap_counter++;
1804  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
1805  part_end, goal - part_end,
1806  type_guid, zero_uuid,
1807  gpt_flags, gpt_name);
1808  if (ret < 0)
1809  return ret;
1810  /* Mark as automatically placed filler request */
1811  t->gpt_req[t->gpt_req_count - 1]->req_status |= 1;
1812  }
1813  }
1814  /* Merge list of gap partitions with list of already sorted entries */
1815  qsort(t->gpt_req, t->gpt_req_count,
1817 
1818  if ((int) t->gpt_max_entries < t->gpt_req_count)
1819  return ISO_BOOT_TOO_MANY_GPT;
1820 
1821  /* Write the GPT entries to buf */
1822  for (i = 0; i < t->gpt_req_count; i++) {
1823  req = t->gpt_req[i];
1824  start_lba = req->start_block;
1825  end_lba = req->start_block + req->block_count;
1826  if (req->start_block == t->opts->partition_offset * ((uint64_t) 4) &&
1827  req->block_count == ((uint64_t) 4) * 0xffffffff)
1828  end_lba = t->vol_space_size * 4;
1829  if (end_lba > backup_end_lba)
1830  end_lba = backup_end_lba;
1831  end_lba = end_lba - 1;
1832  iso_write_gpt_entry(t, buf + 512 * t->gpt_part_start + 128 * i,
1833  req->type_guid, req->partition_guid,
1834  start_lba, end_lba, req->flags, req->name);
1835  }
1836  for (; i < (int) t->gpt_max_entries; i++)
1837  memset(buf + 512 * t->gpt_part_start + 128 * i, 0, 128);
1838 
1839  p_arr_crc = iso_crc32_gpt((unsigned char *) buf + 512 * t->gpt_part_start,
1840  128 * t->gpt_max_entries, 0);
1841  ret = iso_write_gpt_header_block(t, img_blocks, buf + 512,
1842  t->gpt_max_entries,
1843  t->gpt_part_start, p_arr_crc);
1844  if (ret < 0)
1845  return ret;
1846  return ISO_SUCCESS;
1847 }
1848 
1849 
1850 /* Add a dummy MBR partition of type 0 with boot flag */
1851 static void iso_dummy_mbr_partition(uint8_t *buf, int mode)
1852 {
1853  int i;
1854  /* bootable , start 0/0/1, type 0x00, end 0/0/1,
1855  start LBA 0, block count 1 */
1856  static uint8_t dummy_entry[16] = {
1857  0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
1858  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
1859 
1860  for (i = 0; i < 4; i++) {
1861  if (mbr_part_slot_is_unused(buf + 446 + 16 * i)) {
1862  memcpy(buf + 446 + 16 * i, dummy_entry, 16);
1863  return;
1864  }
1865  }
1866  /* Abundance of 0xee and 0xef partitions. No other one free. */
1867  for (i = 0; i < 4; i++) {
1868  if (buf[446 + 16 * i + 4] != 0xef) {
1869  buf[446 + 16 * i] |= 0x80;
1870  return;
1871  }
1872  }
1873  i = 3;
1874  buf[446 + 16 * i] |= 0x80;
1875 }
1876 
1877 
1878 /* @param flag
1879  bit0= t->opts->ms_block is not counted in t->total_size
1880 */
1881 int iso_write_system_area(Ecma119Image *t, uint8_t *buf, int flag)
1882 {
1883  int ret, int_img_blocks, sa_type, i, will_append = 0, do_isohybrid = 0;
1884  int first_partition = 1, last_partition = 4, apm_flag, part_type = 0;
1885  int gpt_count = 0, gpt_idx[128], apm_count = 0, no_boot_mbr = 0;
1886  int offset_flag = 0, risk_of_ee = 0;
1887  uint32_t img_blocks, gpt_blocks, mbrp1_blocks, pml_blocks;
1888  uint64_t blk;
1889  uint8_t *wpt;
1890 
1891  if ((t == NULL) || (buf == NULL)) {
1892  return ISO_NULL_POINTER;
1893  }
1894 
1895  /* set buf to 0s */
1896  memset(buf, 0, 16 * BLOCK_SIZE);
1897 
1898  sa_type = (t->system_area_options >> 2) & 0x3f;
1899 
1900  iso_tell_max_part_range(t->opts, &first_partition, &last_partition, 0);
1901  for (i = first_partition - 1; i <= last_partition - 1; i++)
1902  if (t->opts->appended_partitions[i] != NULL) {
1903  will_append = 1;
1904  break;
1905  }
1906 
1907 #ifdef Libisofs_appended_partitions_inlinE
1908  img_blocks = t->vol_space_size;
1909 #else
1910  img_blocks = t->curblock;
1911 #endif
1912 
1913  if (t->system_area_data != NULL) {
1914  /* Write more or less opaque boot image */
1915  memcpy(buf, t->system_area_data, 16 * BLOCK_SIZE);
1916 
1917  } else if (sa_type == 0 && t->catalog != NULL &&
1918  (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) {
1919  /* Check for isolinux image with magic number of 3.72 and produce
1920  an MBR from our built-in template. (Deprecated since 31 Mar 2010)
1921  */
1922  if (t->bootsrc[0] == NULL)
1924  "Cannot refer by isohybrid MBR to data outside of ISO 9660 filesystem.");
1925  if (img_blocks < 0x80000000) {
1926  int_img_blocks= img_blocks;
1927  } else {
1928  int_img_blocks= 0x7ffffff0;
1929  }
1930  ret = make_isohybrid_mbr(t->bootsrc[0]->sections[0].block,
1931  &int_img_blocks, (char*)buf, 0);
1932  if (ret != 1) {
1933  /* error, it should never happen */
1934  return ISO_ASSERT_FAILURE;
1935  }
1936  return ISO_SUCCESS;
1937  }
1938 
1939  /* If APM entries were submitted to iso_register_apm_entry(), then they
1940  get sprinkled over the system area after the system area template was
1941  loaded and before any other data get inserted.
1942  Note that if APM and MBR get combined, then the first 8 bytes of the MBR
1943  template must be replaceable by:
1944  {0x45, 0x52, 0x08 0x00, 0xeb, 0x02, 0xff, 0xff}
1945 
1946  >>> ts B20526
1947  >>> This does not care for eventual image enlargements in last minute.
1948  >>> A sa_type, that does this, will have to adjust the last APM entry
1949  >>> if exactness matters.
1950  */
1951 
1952  apm_flag = 0;
1953  if (sa_type == 0 && (t->system_area_options & 3) == 2) {
1954  do_isohybrid = 1;
1955 
1956  /* >>> Coordinate with partprepend writer */
1957  /* <<< provisory trap */
1958  if (t->mbr_req_count > 0)
1959  return ISO_BOOT_MBR_OVERLAP;
1960 
1961  /* If own APM is desired, set flag bit0 to prevent writing of Block0
1962  which would interfere with the own Block0 of isohybrid.
1963  */
1964  ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
1965  if (ret < 0)
1966  return ret;
1967  if (apm_count > 0)
1968  apm_flag |= 1;
1969  }
1970 
1971  ret = iso_write_apm(t, img_blocks, buf, apm_flag);
1972  if (ret < 0) {
1973  iso_msg_submit(t->image->id, ret, 0,
1974  "Cannot set up Apple Partition Map");
1975  return ret;
1976  }
1977  ret = iso_write_mbr(t, img_blocks, buf);
1978  if (ret < 0) {
1979  iso_msg_submit(t->image->id, ret, 0,
1980  "Cannot set up MBR partition table");
1981  return ret;
1982  }
1983  if (t->mbr_req_count > 0) {
1984  if (sa_type != 0)
1985  return ISO_NON_MBR_SYS_AREA;
1986  risk_of_ee = 1;
1987  }
1988 
1989  if (t->gpt_backup_outside)
1990  gpt_blocks = t->total_size / BLOCK_SIZE +
1991  (flag & 1) * t->opts->ms_block;
1992  else
1993  gpt_blocks = img_blocks;
1994  ret = iso_write_gpt(t, gpt_blocks, buf);
1995  if (ret < 0) {
1996  iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT");
1997  return ret;
1998  }
1999 
2000  if (sa_type == 0 && (t->system_area_options & 1)) {
2001  if (t->mbr_req_count == 0){
2002  /* Write GRUB protective msdos label, i.e. a simple partition
2003  table */
2004  if (t->gpt_req_count > 0 && ! t->opts->part_like_isohybrid) {
2005  part_type = 0xee;
2006  pml_blocks = gpt_blocks;
2007  } else {
2008  part_type = 0xcd;
2009  if (t->opts->iso_mbr_part_type >= 0 &&
2010  t->opts->iso_mbr_part_type <= 255)
2011  part_type= t->opts->iso_mbr_part_type;
2012  pml_blocks = img_blocks;
2013  }
2014  ret = make_grub_msdos_label(pml_blocks, t->partition_secs_per_head,
2016  (uint8_t) part_type, buf, 0);
2017  if (ret != ISO_SUCCESS) /* error should never happen */
2018  return ISO_ASSERT_FAILURE;
2019  risk_of_ee = 1;
2020  } else if (t->gpt_req_count > 0) {
2021 
2022  /* >>> ??? change first partition type to 0xee */;
2023 
2024  }
2025  } else if (do_isohybrid) {
2026  /* Patch externally provided system area as isohybrid MBR */
2027  if (t->catalog == NULL || t->system_area_data == NULL) {
2028  /* isohybrid makes only sense together with ISOLINUX boot image
2029  and externally provided System Area.
2030  */
2031  return ISO_ISOLINUX_CANT_PATCH;
2032  }
2033 
2034  if (gpt_count > 0 || apm_count > 0)
2035  part_type = 0x00;
2036  else {
2037  part_type = 0x17;
2038  if (t->opts->iso_mbr_part_type >= 0 &&
2039  t->opts->iso_mbr_part_type <= 255)
2040  part_type= t->opts->iso_mbr_part_type;
2041  }
2042 
2044  part_type = 0xee;
2045  risk_of_ee = 1;
2046  img_blocks = gpt_blocks;
2047  no_boot_mbr = 2;
2048  }
2049 
2050  /* >>> ??? Why is partition_offset 0 here ?
2051  It gets adjusted later by iso_offset_partition_start()
2052  Would it harm to give the real offset here ?
2053  */;
2054 
2055  ret = make_isolinux_mbr(&img_blocks, t, 0, 1, part_type, buf,
2056  1 | no_boot_mbr);
2057  if (ret != 1)
2058  return ret;
2059  } else if (sa_type == 1) {
2060  ret = make_mips_volume_header(t, buf, 0);
2061  if (ret != ISO_SUCCESS)
2062  return ret;
2063  } else if (sa_type == 2) {
2064  ret = make_mipsel_boot_block(t, buf, 0);
2065  if (ret != ISO_SUCCESS)
2066  return ret;
2067  } else if (sa_type == 3) {
2068  ret = make_sun_disk_label(t, buf, 0);
2069  if (ret != ISO_SUCCESS)
2070  return ret;
2071  } else if (sa_type == 4 || sa_type == 5) {
2072  /* (By coincidence, sa_type and PALO header versions match) */
2073  ret = make_hppa_palo_sector(t, buf, sa_type, 0);
2074  if (ret != ISO_SUCCESS)
2075  return ret;
2076  } else if (sa_type == 6) {
2077  ret = make_dec_alpha_sector(t, buf, 0);
2078  if (ret != ISO_SUCCESS)
2079  return ret;
2080  } else if ((t->opts->partition_offset > 0 || will_append) &&
2081  sa_type == 0 && t->mbr_req_count == 0) {
2082  /* Write a simple partition table. */
2083  part_type = 0xcd;
2084  if (t->opts->iso_mbr_part_type >= 0 &&
2085  t->opts->iso_mbr_part_type <= 255)
2086  part_type= t->opts->iso_mbr_part_type;
2087  ret = make_grub_msdos_label(img_blocks, t->partition_secs_per_head,
2089  (uint8_t) part_type, buf, 2);
2090  if (ret != ISO_SUCCESS) /* error should never happen */
2091  return ISO_ASSERT_FAILURE;
2092  risk_of_ee = 1;
2094 
2095  /* >>> ??? Do this in any case of t->gpt_req_count > ? */;
2096 
2097  /* Re-write partition entry 1 : protective MBR for GPT */
2098  part_type = 0xee;
2099  risk_of_ee = 1;
2100  ret = write_mbr_partition_entry(1, part_type,
2101  (uint64_t) 1, ((uint64_t) gpt_blocks) * 4 - 1,
2103  buf, 2);
2104  if (ret < 0)
2105  return ret;
2106  } else if (t->opts->partition_offset == 0) {
2107  /* Re-write partition entry 1 : start at 0, type Linux */
2108  blk = ((uint64_t) img_blocks) * 4 - t->post_iso_part_pad / 512;
2109  part_type = 0x83;
2110  if (t->opts->iso_mbr_part_type >= 0 &&
2111  t->opts->iso_mbr_part_type <= 255)
2112  part_type= t->opts->iso_mbr_part_type;
2113  ret = write_mbr_partition_entry(1, part_type, (uint64_t) 0, blk,
2115  buf, 2);
2116  if (ret < 0)
2117  return ret;
2118  }
2119  }
2120 
2121  /* Check for protective MBR in mbr_req and adjust to GPT size */
2122  if (t->gpt_req_count > 0 && sa_type == 0 && t->mbr_req_count == 1) {
2123  if (t->mbr_req[0]->type_byte == 0xee && buf[450] == 0xee &&
2124  t->mbr_req[0]->desired_slot <= 1) {
2125  part_type = 0xee;
2126  risk_of_ee = 1;
2127  ret = write_mbr_partition_entry(1, part_type,
2128  (uint64_t) 1, ((uint64_t) gpt_blocks) * 4 - 1,
2130  buf, 2);
2131  if (ret < 0)
2132  return ret;
2133  }
2134  }
2135 
2136  if (t->opts->partition_offset > 0 && sa_type == 0 &&
2137  t->mbr_req_count == 0) {
2138  /* Adjust partition table to partition offset.
2139  With t->mbr_req_count > 0 this has already been done,
2140  */
2141 
2142 #ifndef Libisofs_appended_partitions_inlinE
2143 
2144  img_blocks = t->curblock; /* value might have been altered */
2145 
2146 #else
2147 
2148  /* A change of t->curblock does not matter in this case */
2149 
2150 #endif
2151 
2152  if (part_type == 0xee && t->gpt_req_count > 0) {
2153  mbrp1_blocks = t->total_size / BLOCK_SIZE +
2154  (flag & 1) * t->opts->ms_block;
2155  offset_flag |= 2 | 1; /* protective MBR, no other partitions */
2156  } else {
2157  mbrp1_blocks = img_blocks;
2158  }
2159  ret = iso_offset_partition_start(mbrp1_blocks, t->post_iso_part_pad,
2160  t->opts->partition_offset,
2162  t->partition_heads_per_cyl, buf,
2163  offset_flag);
2164  if (ret != ISO_SUCCESS) /* error should never happen */
2165  return ISO_ASSERT_FAILURE;
2166  }
2167 
2168  /* This possibly overwrites the non-mbr_req partition table entries
2169  made so far. Overwriting those from t->mbr_req is not allowed.
2170  */
2171  if (sa_type == 3 ||
2172  !(t->opts->appended_as_gpt || t->opts->appended_as_apm)) {
2173  for (i = first_partition - 1; i <= last_partition - 1; i++) {
2174  if (t->opts->appended_partitions[i] == NULL)
2175  continue;
2176  if (i < t->mbr_req_count)
2177  return ISO_BOOT_MBR_COLLISION;
2178  if (sa_type == 3) {
2179  ret = write_sun_partition_entry(i + 1,
2183  buf, t->opts->appended_partitions[i][0] == 0);
2184  } else {
2185  ret = write_mbr_partition_entry(i + 1,
2186  t->opts->appended_part_types[i],
2187  (uint64_t) t->appended_part_start[i],
2188  (uint64_t) t->appended_part_size[i],
2190  buf, 0);
2191  }
2192  if (ret < 0)
2193  return ret;
2194  }
2195  }
2196 
2197  if (sa_type == 0 && (t->system_area_options & 0x4000) && !do_isohybrid) {
2198  /* Patch MBR for GRUB2 */
2199  if (t->num_bootsrc <= 0)
2201  "No boot image found as jump target for GRUB2 MBR.");
2202  if (t->bootsrc[0] == NULL)
2204  "Cannot refer by GRUB2 MBR to data outside of ISO 9660 filesystem.");
2205  blk = t->bootsrc[0]->sections[0].block * 4 +
2207  wpt = buf + Libisofs_grub2_mbr_patch_poS;
2208  for (i = 0; i < 8; i++)
2209  wpt[i] = blk >> (i * 8);
2210  }
2211 
2212  /* Prevent partition type 0xee if no GPT emerged */
2213 
2214  /* >>> ??? check for GPT magic number at byte 512 ff. ? */;
2215 
2216  if (sa_type == 0 && ((t->system_area_options & 3) || risk_of_ee) &&
2217  (t->opts->part_like_isohybrid || t->gpt_req_count == 0) &&
2218  t->opts->iso_mbr_part_type != 0xee) {
2219  for (i = 0; i < 4; i++) {
2220  if (buf[446 + 16 * i + 4] == 0xee) {
2221  iso_msgs_submit(0,
2222  "Prevented partition type 0xEE in MBR without GPT",
2223  0, "WARNING", 0);
2224  part_type = 0xcd;
2225  if (t->opts->iso_mbr_part_type >= 0 &&
2226  t->opts->iso_mbr_part_type <= 255)
2227  part_type= t->opts->iso_mbr_part_type;
2228  buf[446 + 16 * i + 4] = (uint8_t) part_type;
2229  }
2230  }
2231  }
2232 
2233  if (sa_type == 0 && (
2234  (t->system_area_options & 3) ||
2235  (t->system_area_options & (1 << 14)) ||
2236  (((t->system_area_options >> 10) & 15) != 1 &&
2237  (t->system_area_options & (1 << 15)))
2238  )) {
2239  /* This is an MBR which shall have a bootable/active flag
2240  protective-msdos-label, isohybrid, grub2-mbr, mbr-force-bootable
2241  */
2242  for (i = 0; i < 4; i++)
2243  if (buf[446 + 16 * i] & 0x80)
2244  break;
2245  if (i >= 4) { /* no bootable/active flag set yet */
2246  for (i = 0; i < 4; i++) {
2247  if ((!mbr_part_slot_is_unused(buf + 446 + 16 * i)) &&
2248  buf[446 + 16 * i + 4] != 0xee &&
2249  buf[446 + 16 * i + 4] != 0xef) {
2250  buf[446 + 16 * i] |= 0x80;
2251  break;
2252  }
2253  }
2254  if (i >= 4) { /* still no bootable/active flag set */
2255  if (t->system_area_options & (1 << 15)) /* Force it */
2256  iso_dummy_mbr_partition(buf, 0);
2257  }
2258  }
2259  }
2260 
2261  if ((((t->system_area_options >> 2) & 0x3f) == 0 &&
2262  (t->system_area_options & 3) == 1) ||
2263  t->opts->partition_offset > 0) {
2264  /* Protective MBR || partition offset
2265  ISO will not be a partition or add-on session.
2266  It can span the whole image.
2267  */
2268  t->pvd_size_is_total_size = 1;
2269  }
2270 
2271  return ISO_SUCCESS;
2272 }
2273 
2274 /* Choose *heads_per_cyl so that
2275  - *heads_per_cyl * secs_per_head * 1024 >= imgsize / 512
2276  - *heads_per_cyl * secs_per_head is divisible by 4
2277  - it is as small as possible (to reduce alignment overhead)
2278  - it is <= 255
2279  @return 1= success , 0= cannot achieve goals
2280 */
2281 static
2282 int try_sph(off_t imgsize, int secs_per_head, int *heads_per_cyl, int flag)
2283 {
2284  off_t hd_blocks, hpc;
2285 
2286  hd_blocks= imgsize / 512;
2287  hpc = hd_blocks / secs_per_head / 1024;
2288  if (hpc * secs_per_head * 1024 < hd_blocks)
2289  hpc++;
2290  if ((secs_per_head % 4) == 0) {
2291  ;
2292  } else if ((secs_per_head % 2) == 0) {
2293  hpc += (hpc % 2);
2294  } else if(hpc % 4) {
2295  hpc += 4 - (hpc % 4);
2296  }
2297  if (hpc > 255)
2298  return 0;
2299  *heads_per_cyl = hpc;
2300  return 1;
2301 }
2302 
2304 {
2305  int sa_type, ret, always_align;
2306  uint32_t img_blocks;
2307  off_t imgsize, cylsize = 0, frac;
2308  char *msg = NULL;
2309 
2310 #ifdef Libisofs_part_align_writeR
2311  int fap, lap, app_part_count;
2312 #endif
2313 
2314  LIBISO_ALLOC_MEM(msg, char, 160);
2315  sa_type = (t->system_area_options >> 2) & 0x3f;
2316  if (sa_type != 0)
2317  {ret = ISO_SUCCESS; goto ex;}
2318  always_align = (t->system_area_options >> 8) & 3;
2319 
2320  if (!t->gpt_backup_outside) {
2321  /* Take into account the backup GPT */;
2322  ret = precompute_gpt(t);
2323  if (ret < 0)
2324  goto ex;
2325  }
2326 
2327 #ifdef Libisofs_part_align_writeR
2328 
2329  /* If partitions get appended then t->opts->tail_blocks and
2330  t->gpt_backup_size come after the alignment padding.
2331  */
2332  app_part_count = iso_count_appended_partitions(t, &fap, &lap);
2333  img_blocks = t->curblock;
2334  if (app_part_count == 0)
2335  img_blocks += t->opts->tail_blocks + t->gpt_backup_size;
2336 
2337 #else
2338 
2339  img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size;
2340 
2341 #endif
2342 
2343  imgsize = ((off_t) img_blocks) * (off_t) 2048;
2344  if ((!(t->opts->appended_as_gpt && t->have_appended_partitions))
2345  && ((t->system_area_options & 3) || always_align)
2347  * 1024) * (off_t) 512 < imgsize) {
2348  /* Choose small values which can represent the image size */
2349  /* First try 32 sectors per head */
2350  ret = try_sph(imgsize, 32, &(t->partition_heads_per_cyl), 0);
2351  if (ret == 1) {
2352  t->partition_secs_per_head = 32;
2353  } else {
2354  /* Did not work with 32. Try 63 */
2355  t->partition_secs_per_head = 63;
2356  ret = try_sph(imgsize, 63, &(t->partition_heads_per_cyl), 0);
2357  if (ret != 1)
2358  t->partition_heads_per_cyl = 255;
2359  }
2360  cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head *512;
2361  frac = imgsize % cylsize;
2362  sprintf(msg, "Automatically adjusted MBR geometry to %d/%d/%d",
2363  (int) (imgsize / cylsize + !!frac),
2365  iso_msgs_submit(0, msg, 0, "NOTE", 0);
2366  }
2367 
2368  if (always_align == 2)
2369  {ret = ISO_SUCCESS; goto ex;}
2370 
2371  cylsize = 0;
2372  if (t->catalog != NULL &&
2373  (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) {
2374  /* Check for isolinux image with magic number of 3.72 and produce
2375  an MBR from our built-in template. (Deprecated since 31 Mar 2010)
2376  */
2377  if (img_blocks >= 0x40000000)
2378  {ret = ISO_SUCCESS; goto ex;}
2379  cylsize = 64 * 32 * 512;
2380 
2381  } else if (t->system_area_options & 2) {
2382  /* Patch externally provided system area as isohybrid MBR */
2383  if (t->catalog == NULL || t->system_area_data == NULL) {
2384  /* isohybrid makes only sense together with ISOLINUX boot image
2385  and externally provided System Area.
2386  */
2387  {ret = ISO_ISOLINUX_CANT_PATCH; goto ex;}
2388  }
2390  * 512;
2391  } else if (always_align) {
2393  * 512;
2394  }
2395  if (cylsize == 0)
2396  {ret = ISO_SUCCESS; goto ex;}
2397  if (((double) imgsize) / (double) cylsize > 1024.0) {
2398  iso_msgs_submit(0,
2399  "Image size exceeds 1024 cylinders. Cannot align partition.",
2400  0, "WARNING", 0);
2401  iso_msgs_submit(0,
2402  "There are said to be BIOSes which will not boot this via MBR.",
2403  0, "WARNING", 0);
2404  {ret = ISO_SUCCESS; goto ex;}
2405  }
2406 
2407  frac = imgsize % cylsize;
2408  imgsize += (frac > 0 ? cylsize - frac : 0);
2409 
2410  frac = imgsize - ((off_t) img_blocks) * (off_t) 2048;
2411  if (frac == 0)
2412  {ret = ISO_SUCCESS; goto ex;}
2413  t->post_iso_part_pad = 0;
2414  if (frac % 2048) {
2415  t->post_iso_part_pad = 2048 - frac % 2048;
2416  sprintf(msg,
2417  "Cylinder aligned image size is not divisible by 2048. Have to add %d bytes.",
2418  t->post_iso_part_pad);
2419  iso_msgs_submit(0, msg, 0, "WARNING", 0);
2420  }
2421 
2422 #ifdef Libisofs_part_align_writeR
2423 
2424  t->part_align_blocks = (frac + 2047) / 2048;
2425 
2426 #else
2427 
2428  t->opts->tail_blocks += (frac + 2047) / 2048;
2429 
2430 #endif /* ! Libisofs_part_align_writeR */
2431 
2432  ret = ISO_SUCCESS;
2433 ex:;
2434  LIBISO_FREE_MEM(msg);
2435  return ret;
2436 }
2437 
2438 
2440  int *apm_req_count,
2441  struct iso_apm_partition_request *req, int flag)
2442 {
2443  struct iso_apm_partition_request *entry;
2444 
2445  if (*apm_req_count >= ISO_APM_ENTRIES_MAX)
2446  return ISO_BOOT_TOO_MANY_APM;
2447  entry = calloc(1, sizeof(struct iso_apm_partition_request));
2448  if (entry == NULL)
2449  return ISO_OUT_OF_MEM;
2450 
2451  memcpy(entry, req, sizeof(struct iso_apm_partition_request));
2452  req_array[*apm_req_count] = entry;
2453  (*apm_req_count)++;
2454  return ISO_SUCCESS;
2455 }
2456 
2457 
2459  int *mbr_req_count,
2460  struct iso_mbr_partition_request *req, int flag)
2461 {
2462  struct iso_mbr_partition_request *entry;
2463 
2464  if (*mbr_req_count >= ISO_MBR_ENTRIES_MAX)
2465  return ISO_BOOT_TOO_MANY_MBR;
2466  entry = calloc(1, sizeof(struct iso_mbr_partition_request));
2467  if (entry == NULL)
2468  return ISO_OUT_OF_MEM;
2469 
2470  memcpy(entry, req, sizeof(struct iso_mbr_partition_request));
2471  req_array[*mbr_req_count] = entry;
2472  (*mbr_req_count)++;
2473  return ISO_SUCCESS;
2474 }
2475 
2477  int *gpt_req_count,
2478  struct iso_gpt_partition_request *req, int flag)
2479 {
2480  struct iso_gpt_partition_request *entry;
2481 
2482  if (*gpt_req_count >= ISO_GPT_ENTRIES_MAX)
2483  return ISO_BOOT_TOO_MANY_GPT;
2484  entry = calloc(1, sizeof(struct iso_gpt_partition_request));
2485  if (entry == NULL)
2486  return ISO_OUT_OF_MEM;
2487 
2488  memcpy(entry, req, sizeof(struct iso_gpt_partition_request));
2489  req_array[*gpt_req_count] = entry;
2490  (*gpt_req_count)++;
2491  return ISO_SUCCESS;
2492 }
2493 
2494 #ifdef Libisofs_with_uuid_generatE
2495 
2496 static void swap_uuid(void *u_pt)
2497 {
2498  uint8_t tr, *u;
2499 
2500  u = (uint8_t *) u_pt;
2501  tr = u[0]; u[0] = u[3]; u[3] = tr;
2502  tr = u[1]; u[1] = u[2]; u[2] = tr;
2503  tr = u[4]; u[4] = u[5]; u[5] = tr;
2504  tr = u[6]; u[6] = u[7]; u[7] = tr;
2505 }
2506 
2507 #endif /* Libisofs_with_uuid_generatE */
2508 
2509 
2510 /* CRC-32 as of GPT and Ethernet.
2511  Parameters are deduced from a table driven implementation in isohybrid.c
2512 */
2513 uint32_t iso_crc32_gpt(unsigned char *data, int count, int flag)
2514 {
2515  unsigned int acc, top, result = 0;
2516  long int i;
2517 
2518  /* Chosen so that the CRC of 0 bytes of input is 0x00000000 */
2519  acc = 0x46af6449;
2520 
2521  /* Process data bits and flush numerator by 32 zero bits */
2522  for (i = 0; i < count * 8 + 32; i++) {
2523  top = acc & 0x80000000;
2524  acc = (acc << 1);
2525  if (i < count * 8)
2526  /* The least significant bits of input bytes get processed first */
2527  acc |= ((data[i / 8] >> (i % 8)) & 1);
2528  if (top)
2529  /* Division by the generating polynomial */
2530  acc ^= 0x04c11db7;
2531  }
2532  /* Mirror residue bits */
2533  for (i = 0; i < 32; i++)
2534  if (acc & (1 << i))
2535  result |= 1 << (31 - i);
2536  /* Return bit complement */
2537  return result ^ 0xffffffff;
2538 }
2539 
2540 void iso_mark_guid_version_4(uint8_t *u)
2541 {
2542  /* Mark as UUID version 4. RFC 4122 says u[6], but UEFI prescribes
2543  bytes 6 and 7 to be swapped.
2544  */
2545  u[7] = (u[7] & 0x0f) | 0x40;
2546 
2547  /* Variant is "1 0 x" as described in RFC 4122.
2548  */
2549  u[8] = (u[8] & 0x3f) | 0x80;
2550 
2551  return;
2552 }
2553 
2554 void iso_generate_gpt_guid(uint8_t guid[16])
2555 {
2556 
2557 #ifdef Libisofs_with_uuid_generatE
2558 
2559  uuid_t u;
2560 
2561  uuid_generate(u);
2562  swap_uuid((void *) u);
2563  memcpy(guid, u, 16);
2564 
2565 #else
2566 
2567  uint8_t *u;
2568  /* produced by uuid_generate() and byte-swapped to UEFI specs */
2569  static uint8_t uuid_template[16] = {
2570  0xee, 0x29, 0x9d, 0xfc, 0x65, 0xcc, 0x7c, 0x40,
2571  0x92, 0x61, 0x5b, 0xcd, 0x6f, 0xed, 0x08, 0x34
2572  };
2573  uint32_t rnd, salt;
2574  struct timeval tv;
2575  pid_t pid;
2576  int i, ret, fd;
2577 
2578  u = guid;
2579 
2580  /* First try /dev/urandom
2581  */
2582  fd = open("/dev/urandom", O_RDONLY | O_BINARY);
2583  if (fd == -1)
2584  goto fallback;
2585  ret = read(fd, u, 16);
2586  if (ret != 16) {
2587  close(fd);
2588  goto fallback;
2589  }
2590  close(fd);
2592  return;
2593 
2594 
2595 fallback:;
2596  pid = getpid();
2597  salt = iso_crc32_gpt((unsigned char *) &guid, sizeof(uint8_t *), 0) ^ pid;
2598 
2599  /* This relies on the uniqueness of the template and the rareness of
2600  bootable ISO image production via libisofs. Estimated 48 bits of
2601  entropy should influence the production of a single day.
2602  So first collisions are to be expected with about 16 million images
2603  per day.
2604  */
2605  memcpy(u, uuid_template, 16);
2606  gettimeofday(&tv, NULL);
2607  for (i = 0; i < 4; i++)
2608  u[i] = (salt >> (8 * i)) & 0xff;
2609  for (i = 0; i < 2; i++)
2610  u[4 + i] = (pid >> (8 * i)) & 0xff;
2611  u[6] = ((salt >> 8) ^ (pid >> 16)) & 0xff;
2612  rnd = ((0xffffff & tv.tv_sec) << 8) |
2613  (((tv.tv_usec >> 16) ^ (salt & 0xf0)) & 0xff);
2614  for (i = 0; i < 4; i++)
2615  u[10 + i] ^= (rnd >> (8 * i)) & 0xff;
2616  u[14] ^= (tv.tv_usec >> 8) & 0xff;
2617  u[15] ^= tv.tv_usec & 0xff;
2618 
2620  return;
2621 
2622 #endif /* ! Libisofs_with_uuid_generatE */
2623 
2624 }
2625 
2626 void iso_gpt_uuid(Ecma119Image *t, uint8_t uuid[16])
2627 {
2628  if (t->gpt_uuid_counter == 0)
2630 
2631  memcpy(uuid, t->gpt_uuid_base, 16);
2632 
2633  /* Previous implementation changed only byte 9. So i expand it by applying
2634  the counter in little-endian style.
2635  */
2636  uuid[9] ^= t->gpt_uuid_counter & 0xff;
2637  uuid[10] ^= (t->gpt_uuid_counter >> 8) & 0xff;
2638  uuid[11] ^= (t->gpt_uuid_counter >> 16) & 0xff;
2639  uuid[12] ^= (t->gpt_uuid_counter >> 24) & 0xff;
2640  t->gpt_uuid_counter++;
2641  return;
2642 }
2643 
2645 {
2646  static uint8_t basic_data_uuid[16] = {
2647  0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
2648  0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
2649  };
2650  static uint8_t efi_sys_uuid[16] = {
2651  0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
2652  0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b
2653  };
2654  static uint8_t hfs_plus_uuid[16] = {
2655  0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
2656  0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
2657  };
2658  static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2659  int i, ret, do_apm = 0, do_gpt = 0, index, already_in_gpt = 0;
2660  uint8_t gpt_name[72], *type_uuid;
2661  char apm_type[33];
2662 
2663 #ifndef Libisofs_appended_partitions_inlinE
2664  if (!t->gpt_backup_outside)
2665  return 2;
2666 #endif
2667 
2668  if ((t->apm_req_count > 0 && t->opts->part_like_isohybrid) ||
2670  do_apm = 1;
2671  if (t->gpt_req_count > 0 ||
2673  do_gpt = 1;
2674 
2675  if (do_apm == 0 && do_gpt == 0)
2676  return 2;
2677 
2678  /* Represent appended partitions */
2679  for (i = 0; i <= 3; i++) {
2680  if (t->opts->appended_partitions[i] == NULL)
2681  continue;
2682  if (do_apm) {
2683  memset(gpt_name, 0, 32);
2684  sprintf((char *) gpt_name, "Appended%d", i + 1);
2685  strcpy(apm_type, "Data");
2686  if (t->opts->appended_part_gpt_flags[i] & 1) {
2687  if (memcmp(t->opts->appended_part_type_guids[i], hfs_plus_uuid,
2688  16) == 0)
2689  strcpy(apm_type, "Apple_HFS");
2690  }
2691  ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
2694  (char *) gpt_name, apm_type);
2695  if (ret < 0)
2696  return ret;
2697  }
2698  if (do_gpt)
2699  already_in_gpt = iso_find_gpt_entry(t->gpt_req, t->gpt_req_count,
2700  ((uint64_t) t->appended_part_start[i]) * 4,
2701  ((uint64_t) t->appended_part_size[i]) * 4,
2702  &index, 0);
2703  if (do_gpt && !already_in_gpt) {
2704  memset(gpt_name, 0, 72);
2705  sprintf((char *) gpt_name, "Appended%d", i + 1);
2706  iso_ascii_utf_16le(gpt_name);
2707  if (t->opts->appended_part_gpt_flags[i] & 1)
2708  type_uuid = t->opts->appended_part_type_guids[i];
2709  else if (t->opts->appended_part_types[i] == 0xef)
2710  type_uuid = efi_sys_uuid;
2711  else
2712  type_uuid = basic_data_uuid;
2713  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
2714  ((uint64_t) t->appended_part_start[i]) * 4,
2715  ((uint64_t) t->appended_part_size[i]) * 4,
2716  type_uuid, zero_uuid,
2717  (uint64_t) 0, gpt_name);
2718  if (ret < 0)
2719  return ret;
2720  }
2721  }
2722  return ISO_SUCCESS;
2723 }
2724 
2725 /* Probably already called by tail_writer_compute_data_blocks via
2726  iso_align_isohybrid
2727 */
2729 {
2730  uint32_t gpt_part_start;
2731  int ret, sa_type;
2732  int gpt_count, gpt_idx[128], apm_count;
2733 
2734  /* Avoid repetition by gpt_tail_writer_compute_data_blocks */
2735  t->gpt_is_computed = 1;
2736 
2737 
2738  /* Assess APM and GPT requests of isohybrid */
2739  sa_type = (t->system_area_options >> 2) & 0x3f;
2740  if (sa_type == 0 && (t->system_area_options & 3) == 2) {
2741 
2742  /* >>> ISOHYBRID :
2743  Shall isohybrid be combinable with other APM and GPT requesters ?
2744  */;
2745  /* <<< provisorily: Not compatible */
2746  ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
2747  if (ret < 0)
2748  return ret;
2749  if (t->gpt_req_count > 0 && gpt_count > 0)
2750  return ISO_BOOT_GPT_OVERLAP;
2751  if (t->apm_req_count > 0 && apm_count > 0)
2752  return ISO_BOOT_APM_OVERLAP;
2753  /* Register the GPT and APM partition entries */
2754  ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 1);
2755  if (ret < 0)
2756  return ret;
2757  }
2758 
2759  /* With part_like_isohybrid:
2760  If no GPT is registered yet, and MBR, but neither CHRP nor ISOLINUX
2761  isohybrid is desired, then try to apply the isohybrid GPT and APM flags
2762  nevertheless. Avoid an overall ISO image GPT partition.
2763  */
2764  if (t->opts->part_like_isohybrid && t->gpt_req_count <= 0 &&
2765  ((t->system_area_options >> 2) & 0x3f) == 0 &&
2766  ((t->system_area_options >> 10) & 0xf) != 1 &&
2767  (!(t->system_area_options & 2))) {
2768 
2769  ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count,
2770  1 | ((t->apm_req_count > 0) << 1) | 4);
2771  if (ret <= 0)
2772  return ret;
2773  t->apm_req_flags |= 2; /* Do not fill APM gaps,
2774  do not adjust final APM partition size */
2775  }
2776 
2777  /* Assess impact of appended partitions on GPT */
2778  ret = assess_appended_gpt(t, 0);
2779  if (ret < 0)
2780  return ret;
2781 
2782  /* Rectify APM requests early in order to learn the size of GPT.
2783  iso_write_apm() relies on this being already done here.
2784  So perform even if no GPT is required.
2785  */
2786  ret = rectify_apm(t);
2787  if (ret < 0)
2788  return ret;
2789 
2790 #ifdef NIX
2791  /* Disabled */
2792 
2793  /* <<< ts B20526 : Dummy mock-up */
2794  if (t->gpt_req_count <= 0) {
2795 
2796  /* <<< ??? Move to system_area.h and publish as macro ?
2797  Or to make_isohybrid_mbr.c ?
2798  */
2799  static uint8_t hfs_uuid[16] = {
2800  0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
2801  0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
2802  };
2803  static uint8_t basic_data_uuid[16] = {
2804  0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
2805  0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
2806  };
2807 
2808  uint8_t gpt_name[72];
2809  static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2810  static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
2811 
2812  memset(gpt_name, 0, 72);
2813  gpt_name[0] = 'T'; gpt_name[2] = '1';
2814  strcpy((char *) gpt_name, "GPT Test 1");
2815  iso_ascii_utf_16le(gpt_name);
2816  /*
2817  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
2818  (uint64_t) (16 * 4), (uint64_t) (20 * 4),
2819  hfs_uuid, zero_uuid, gpt_flags, gpt_name);
2820  / * Caution: Size 90 causes intentional partition overlap error * /
2821  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
2822  (uint64_t) (30 * 4), (uint64_t) (90 * 4),
2823  hfs_uuid, zero_uuid,
2824  gpt_flags, gpt_name);
2825  */
2826  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
2827  (uint64_t) (30 * 4), (uint64_t) (40 * 4),
2828  hfs_uuid, zero_uuid,
2829  gpt_flags, gpt_name);
2830  if (ret < 0)
2831  return ret;
2832  strcpy((char *) gpt_name, "GPT Test 2");
2833  iso_ascii_utf_16le(gpt_name);
2834  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
2835  (uint64_t) (110 * 4), (uint64_t) (60 * 4),
2836  basic_data_uuid, zero_uuid,
2837  gpt_flags, gpt_name);
2838  if (ret < 0)
2839  return ret;
2840  }
2841 #endif /* NIX */
2842 
2843  /* Is a GPT requested ? */
2844  t->gpt_backup_end = 0;
2845  t->gpt_max_entries = 0;
2846  if (t->gpt_req_count == 0)
2847  return ISO_SUCCESS;
2848 
2849  /* Determine GPT partition start in System Area, */
2850  gpt_part_start = 0;
2851  if (t->apm_req_count > 0) {
2852  if (t->opts->apm_block_size == 0)
2853  t->opts->apm_block_size = 2048;
2854  gpt_part_start = (t->apm_req_count + 1) *
2855  (t->opts->apm_block_size / 512);
2856  }
2857  if (gpt_part_start < 2)
2858  gpt_part_start = 2;
2859  else if (gpt_part_start >= 64)
2860  return ISO_BOOT_TOO_MANY_GPT;
2861  t->gpt_part_start = gpt_part_start;
2862 
2863  /* Necessary number of 2K blocks */
2864  t->gpt_max_entries = (64 - t->gpt_part_start) * 4;
2865  t->gpt_backup_size = ((t->gpt_max_entries / 4 + 1) * 512 + 2047) / 2048;
2866 
2867  return ISO_SUCCESS;
2868 }
2869 
2870 
2872 {
2873  Ecma119Image *t;
2874  int ret;
2875 
2876  if (writer == NULL)
2877  return ISO_ASSERT_FAILURE;
2878  t = writer->target;
2879 
2880  if (! t->gpt_is_computed) {
2881  ret = precompute_gpt(t);
2882  if (ret < 0)
2883  return ret;
2884  }
2885 
2886  if (t->gpt_backup_outside) {
2887  t->total_size += t->gpt_backup_size * 2048;
2888  /* The ISO block number after the backup GPT header */
2890  } else {
2891  t->curblock += t->gpt_backup_size;
2892  /* The ISO block number after the backup GPT header */
2893  t->gpt_backup_end = t->curblock;
2894  }
2895 
2896  return ISO_SUCCESS;
2897 }
2898 
2899 
2901 {
2902  return ISO_SUCCESS;
2903 }
2904 
2905 
2907 {
2908  Ecma119Image *t;
2909  uint8_t *head, *new_head, *entries;
2910  uint8_t *backup_buf = NULL;
2911  uint32_t crc, i;
2912  uint64_t part_start;
2913  int ret;
2914 
2915  t = writer->target;
2916  if (t->gpt_backup_end == 0 || t->gpt_max_entries == 0)
2917  return ISO_SUCCESS; /* No backup GPT area reserved by compute_data() */
2918 
2919  backup_buf = calloc(1, t->gpt_backup_size * 2048);
2920  if (backup_buf == NULL)
2921  return ISO_OUT_OF_MEM;
2922  memset(backup_buf, 0, t->gpt_backup_size * 2048);
2923 
2924  /* Check whether GPT header block came through */
2925  head = t->sys_area_as_written + 512;
2926  if (strncmp((char *) head, "EFI PART", 8) != 0) {
2927 tampered_head:;
2928  /* Send error message but do not prevent further image production */
2929  iso_msgs_submit(0,
2930  "GPT header block was altered before writing to System Area.",
2931  0, "FAILURE", 0);
2932  goto write_zeros;
2933  }
2934  for (i = 92; i < 512; i++)
2935  if (head[i])
2936  goto tampered_head;
2937 
2938  /* Patch memorized header block */
2939  new_head = backup_buf + t->gpt_backup_size * 2048 - 512;
2940  memcpy(new_head, head, 512);
2941  /* Exchange "Location of this header" and "Location of header backup" */
2942  memcpy(new_head + 24, head + 32, 8);
2943  memcpy(new_head + 32, head + 24, 8);
2944  /* Point to the backup partition entries */
2945  part_start = ((uint64_t) t->gpt_backup_end) * 4
2946  - 1 - t->gpt_max_entries / 4;
2947  iso_lsb(new_head + 72, part_start & 0xffffffff, 4);
2948  iso_lsb(new_head + 76, (part_start >> 32) & 0xffffffff, 4);
2949 
2950  /* Compute new header CRC */
2951  memset(new_head + 16, 0, 4);
2952  crc = iso_crc32_gpt((unsigned char *) new_head, 92, 0);
2953  iso_lsb(new_head + 16, crc, 4);
2954 
2955  /* Copy GPT entries */
2956  entries = t->sys_area_as_written + t->gpt_part_start * 512;
2957  memcpy(new_head - t->gpt_max_entries * 128,
2958  entries, t->gpt_max_entries * 128);
2959 
2960  ret = iso_write(t, backup_buf, t->gpt_backup_size * 2048);
2961  free(backup_buf);
2962  if (ret < 0)
2963  return ret;
2964 
2965  if (!t->gpt_backup_outside) {
2966 
2967  /* >>> Why isn't t->curblock updated ? */;
2968 
2969  }
2970  return ISO_SUCCESS;
2971 
2972 write_zeros:;
2973  ret = iso_write(t, backup_buf, t->gpt_backup_size * 2048);
2974  free(backup_buf);
2975  if (ret < 0)
2976  return ret;
2977  return ISO_SUCCESS;
2978 }
2979 
2980 
2982 {
2983  return ISO_SUCCESS;
2984 }
2985 
2986 
2988 {
2989  IsoImageWriter *writer;
2990 
2991  writer = calloc(1, sizeof(IsoImageWriter));
2992  if (writer == NULL) {
2993  return ISO_OUT_OF_MEM;
2994  }
2999  writer->data = NULL;
3000  writer->target = target;
3001 
3002  /* add this writer to image */
3003  target->writers[target->nwriters++] = writer;
3004 
3005  return ISO_SUCCESS;
3006 }
3007 
3008 
3009 /* ---------------------- Partition Prepend Writer --------------------- */
3010 
3011 
3013 {
3014  Ecma119Image *t;
3015  IsoFileSrc *src;
3016  int ret, will_have_gpt = 0, with_chrp = 0, i, part_type, keep;
3017  static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3018  static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
3019  uint8_t gpt_name[72];
3020  uint64_t part_start;
3021  off_t start_byte, byte_count;
3022 
3023  /* <<< ??? Move to system_area.h and publish as macro ? */
3024  static uint8_t efi_sys_uuid[16] = {
3025  0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11,
3026  0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b
3027  };
3028 
3029  if (writer == NULL)
3030  return ISO_ASSERT_FAILURE;
3031  t = writer->target;
3032 
3033  with_chrp = ((t->system_area_options & 0x3cff) == 0x0400);
3034  if (t->opts->efi_boot_partition != NULL ||
3035  t->gpt_req_count > 0) /* Might not catch all cases with GPT */
3036  will_have_gpt = 1;
3037 
3038  if (t->opts->efi_boot_partition != NULL) {
3039  keep = 0;
3040  if (t->efi_boot_part_filesrc != NULL) {
3041  /* A file in the emerging ISO image shall store its content
3042  as prepended partition.
3043  Install absolute block addresses and determine partition size.
3044  */
3045  src = t->efi_boot_part_filesrc;
3046  t->efi_boot_part_size = 0;
3047  for (i = 0; i < src->nsections; i++) {
3048  src->sections[i].block = t->curblock + t->efi_boot_part_size;
3049  t->efi_boot_part_size += (src->sections[i].size + 2047) / 2048;
3050  }
3051  part_start = t->curblock * 4;
3052  } else {
3054  &(t->efi_boot_part_size),
3055  t->opts->efi_boot_part_flag & 1);
3056  if (ret < 0)
3057  return ret;
3058  part_start = t->curblock * 4;
3059  if (ret == ISO_SUCCESS + 1) {
3060  /* Interval from imported_iso in add-on session will be kept */
3063  &start_byte, &byte_count, 0);
3064  if (ret < 0)
3065  return ret;
3066  part_start = start_byte / 512;
3067  keep = 1;
3068  }
3069  }
3070  memset(gpt_name, 0, 72);
3071  strcpy((char *) gpt_name, "EFI boot partition");
3072  iso_ascii_utf_16le(gpt_name);
3073  ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), part_start,
3074  ((uint64_t) t->efi_boot_part_size) * 4,
3075  efi_sys_uuid, zero_uuid, gpt_flags, gpt_name);
3076  if (ret < 0)
3077  return ret;
3078  if (!keep)
3079  t->curblock += t->efi_boot_part_size;
3080  }
3081 
3082  if (with_chrp) {
3083  /* CHRP is not compatible with any other partition in MBR */
3084  if (t->opts->prep_partition != NULL || t->opts->fat || will_have_gpt ||
3085  t->mbr_req_count > 0)
3086  return ISO_BOOT_MBR_OVERLAP;
3087  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
3088  (uint64_t) 0, (uint64_t) 0, 0x96, 0x80, 0);
3089  if (ret < 0)
3090  return ret;
3091  return ISO_SUCCESS;
3092  }
3093 
3094  part_start = t->curblock * 4;
3095  keep = 0;
3096  if (t->opts->prep_partition != NULL) {
3098  &(t->prep_part_size),
3099  t->opts->prep_part_flag & 1);
3100  if (ret < 0)
3101  return ret;
3102  if (ret == ISO_SUCCESS + 1) {
3103  /* Interval from imported_iso in add-on session will be kept */
3105  t->opts->prep_partition,
3106  &start_byte, &byte_count, 0);
3107  if (ret < 0)
3108  return ret;
3109  part_start = start_byte / 512;
3110  keep = 1;
3111  }
3112  }
3113  if (t->prep_part_size > 0 || t->opts->fat || will_have_gpt) {
3114  /* Protecting MBR entry for ISO start or whole ISO */
3115  part_type = 0xcd;
3116  if (t->opts->iso_mbr_part_type >= 0 &&
3117  t->opts->iso_mbr_part_type <= 255)
3118  part_type= t->opts->iso_mbr_part_type;
3119  if (will_have_gpt)
3120  part_type = 0xee;
3121  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
3122  will_have_gpt ? (uint64_t) 1 :
3123  ((uint64_t) t->opts->partition_offset) * 4,
3124  (uint64_t) 0, part_type, 0, 0);
3125  if (ret < 0)
3126  return ret;
3127  }
3128  if (t->prep_part_size > 0) {
3129  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), part_start,
3130  ((uint64_t) t->prep_part_size) * 4,
3131  0x41, 0, 0);
3132  if (ret < 0)
3133  return ret;
3134  if (!keep) {
3135  t->curblock += t->prep_part_size;
3136  part_start = t->curblock * 4;
3137  } else {
3138  part_start += t->prep_part_size * 4;
3139  }
3140  } else {
3141  part_start = t->curblock * 4;
3142  }
3143  if (t->prep_part_size > 0 || t->opts->fat) {
3144  /* FAT partition or protecting MBR entry for ISO end */
3145  ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
3146  part_start, (uint64_t) 0,
3147  t->opts->fat ? 0x0c : 0xcd, 0, 0);
3148  if (ret < 0)
3149  return ret;
3150  }
3151 
3152  return ISO_SUCCESS;
3153 }
3154 
3155 
3157 {
3158  return ISO_SUCCESS;
3159 }
3160 
3161 
3163 {
3164  Ecma119Image *t;
3165  int ret;
3166 
3167  t = writer->target;
3168 
3169  if (t->opts->efi_boot_partition != NULL && t->efi_boot_part_size) {
3170 
3171  if (t->efi_boot_part_filesrc != NULL) {
3173  NULL, NULL, 0);
3174  } else {
3176  (uint32_t) 0, t->efi_boot_part_size,
3177  t->opts->efi_boot_part_flag & 1);
3178  }
3179  if (ret < 0)
3180  return ret;
3181  }
3182  if (t->opts->prep_partition != NULL && t->prep_part_size) {
3184  (uint32_t) 0, t->prep_part_size,
3185  t->opts->prep_part_flag & 1);
3186  if (ret < 0)
3187  return ret;
3188  }
3189 
3190  return ISO_SUCCESS;
3191 }
3192 
3193 
3195 {
3196  return ISO_SUCCESS;
3197 }
3198 
3199 
3201 {
3202  IsoImageWriter *writer;
3203 
3204  writer = calloc(1, sizeof(IsoImageWriter));
3205  if (writer == NULL) {
3206  return ISO_OUT_OF_MEM;
3207  }
3208 
3213  writer->data = NULL;
3214  writer->target = target;
3215 
3216  /* add this writer to image */
3217  target->writers[target->nwriters++] = writer;
3218 
3219  return ISO_SUCCESS;
3220 }
3221 
3222 
3223 #ifdef Libisofs_appended_partitions_inlinE
3224 
3225 /* ----------------- Inline Partition Append Writer ------------------ */
3226 
3227 
3229 {
3230  int ret;
3231 
3232  ret = iso_compute_append_partitions(writer->target, 1);
3233  return ret;
3234 }
3235 
3236 
3238 {
3239  return ISO_SUCCESS;
3240 }
3241 
3242 
3244 {
3245  Ecma119Image *target;
3246  int res, first_partition = 1, last_partition = 0;
3247  int i;
3248 
3249  target = writer->target;
3250 
3251  /* Append partition data */
3252  iso_tell_max_part_range(target->opts,
3253  &first_partition, &last_partition, 0);
3254 
3255  for (i = first_partition - 1; i <= last_partition - 1; i++) {
3256  if (target->opts->appended_partitions[i] == NULL)
3257  continue;
3258  if (target->opts->appended_partitions[i][0] == 0)
3259  continue;
3260  res = iso_write_partition_file(target,
3261  target->opts->appended_partitions[i],
3262  target->appended_part_prepad[i],
3263  target->appended_part_size[i],
3264  target->opts->appended_part_flags[i] & 1);
3265  if (res < 0)
3266  return res;
3267  target->curblock += target->appended_part_size[i];
3268  }
3269  return ISO_SUCCESS;
3270 }
3271 
3272 
3274 {
3275  return ISO_SUCCESS;
3276 }
3277 
3278 
3280 {
3281  IsoImageWriter *writer;
3282 
3283  writer = calloc(1, sizeof(IsoImageWriter));
3284  if (writer == NULL) {
3285  return ISO_OUT_OF_MEM;
3286  }
3287 
3292  writer->data = NULL;
3293  writer->target = target;
3294 
3295  /* add this writer to image */
3296  target->writers[target->nwriters++] = writer;
3297 
3298  return ISO_SUCCESS;
3299 }
3300 
3301 #endif /* Libisofs_appended_partitions_inlinE */
3302 
3303 
3305 {
3306  int i, widx;
3307 
3308  /* Dispose the requests with req_status bit0 */
3309  for (i = 0; i < target->gpt_req_count; i++) {
3310  if (target->gpt_req[i]->req_status & 1) {
3311  free(target->gpt_req[i]);
3312  target->gpt_req[i] = NULL;
3313  }
3314  }
3315  /* Densify the request arrays */
3316  widx = 0;
3317  for (i = 0; i < target->gpt_req_count; i++) {
3318  if (target->gpt_req[i] != NULL) {
3319  target->gpt_req[widx] = target->gpt_req[i];
3320  widx++;
3321  }
3322  }
3323  target->gpt_req_count = widx;
3324 
3325  /* And again for APM */
3326  for (i = 0; i < target->apm_req_count; i++) {
3327  if (target->apm_req[i]->req_status & 1) {
3328  free(target->apm_req[i]);
3329  target->apm_req[i] = NULL;
3330  }
3331  }
3332  widx = 0;
3333  for (i = 0; i < target->apm_req_count; i++) {
3334  if (target->apm_req[i] != NULL) {
3335  target->apm_req[widx] = target->apm_req[i];
3336  widx++;
3337  }
3338  }
3339  target->apm_req_count = widx;
3340 }
3341 
#define BLOCK_SIZE
Definition: buffer.h:23
int iso_interval_reader_new(IsoImage *img, char *path, struct iso_interval_reader **ivr, off_t *byte_count, int flag)
Definition: ecma119.c:1760
int iso_write(Ecma119Image *target, void *buf, size_t count)
Definition: ecma119.c:3471
void iso_tell_max_part_range(IsoWriteOpts *opts, int *first_partition, int *last_partition, int flag)
Definition: ecma119.c:4637
int iso_write_partition_file(Ecma119Image *target, char *path, uint32_t prepad, uint32_t blocks, int flag)
Definition: ecma119.c:2091
int iso_interval_reader_keep(Ecma119Image *target, struct iso_interval_reader *ivr, int flag)
Definition: ecma119.c:2050
int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag)
Definition: ecma119.c:1738
int iso_count_appended_partitions(Ecma119Image *target, int *first_partition, int *last_partition)
Definition: ecma119.c:4657
int iso_interval_reader_start_size(Ecma119Image *t, char *path, off_t *start_byte, off_t *byte_count, int flag)
Definition: ecma119.c:2072
#define ISO_GPT_ENTRIES_MAX
Definition: ecma119.h:87
#define ISO_SUN_CYL_SIZE
Definition: ecma119.h:54
#define ISO_MBR_ENTRIES_MAX
Definition: ecma119.h:81
#define ISO_MAX_PARTITIONS
Definition: ecma119.h:47
#define ISO_APM_ENTRIES_MAX
Definition: ecma119.h:77
Ecma119Node * ecma119_search_iso_node(Ecma119Image *img, IsoNode *node)
@ ECMA119_FILE
Definition: ecma119_tree.h:18
static off_t file_size(struct burn_source *source)
Definition: file.c:96
int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file, char *name, char *buffer, int flag)
Definition: filesrc.c:430
static uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
Definition: isofs_wrap.c:78
uint32_t iso_read_msb(const uint8_t *buf, int bytes)
Definition: util.c:1531
int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag)
Definition: util.c:1510
void iso_msb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1494
uint64_t iso_read_lsb64(const uint8_t *buf)
Definition: util.c:1554
void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1478
#define LIBISO_FREE_MEM(pt)
Definition: util.h:627
#define LIBISO_ALLOC_MEM(pt, typ, count)
Definition: util.h:615
IsoStream * iso_file_get_stream(IsoFile *file)
Definition: node.c:1161
#define ISO_BOOT_TOO_MANY_MBR
Definition: libisofs.h:9131
#define ISO_BAD_PARTITION_NO
Definition: libisofs.h:9071
#define ISO_BOOT_MBR_OVERLAP
Definition: libisofs.h:9134
#define ISO_BOOT_IMAGE_NOT_VALID
Definition: libisofs.h:8780
#define ISO_SUCCESS
Definition: libisofs.h:8719
#define ISO_BOOT_FILE_MISSING
Definition: libisofs.h:9068
@ LIBISO_FILE
Definition: libisofs.h:230
#define ISO_BOOT_GPT_OVERLAP
Definition: libisofs.h:9128
#define ISO_BOOT_APM_OVERLAP
Definition: libisofs.h:9122
#define ISO_HPPA_PALO_OFLOW
Definition: libisofs.h:9171
#define ISO_BOOT_TOO_MANY_GPT
Definition: libisofs.h:9125
int iso_stream_open(IsoStream *stream)
Definition: stream.c:798
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
#define ISO_HPPA_PALO_INCOMPL
Definition: libisofs.h:9168
off_t iso_stream_get_size(IsoStream *stream)
Definition: stream.c:810
const char * iso_node_get_name(const IsoNode *node)
Definition: node.c:415
#define ISO_HPPA_PALO_NOTREG
Definition: libisofs.h:9174
#define ISO_BAD_PARTITION_FILE
Definition: libisofs.h:9074
#define ISO_HPPA_PALO_CMDLEN
Definition: libisofs.h:9177
#define ISO_BOOT_MBR_COLLISION
Definition: libisofs.h:9137
#define ISO_WRONG_ARG_VALUE
Definition: libisofs.h:8751
int iso_stream_read(IsoStream *stream, void *buf, size_t count)
Definition: stream.c:816
int iso_msgs_submit(int error_code, char msg_text[], int os_errno, char severity[], int origin)
Definition: messages.c:707
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
#define ISO_BOOT_TOO_MANY_APM
Definition: libisofs.h:9119
#define ISO_BOOT_APM_GPT_BSIZE
Definition: libisofs.h:9147
#define ISO_ISOLINUX_CANT_PATCH
Definition: libisofs.h:8897
int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
Definition: tree.c:1237
enum IsoNodeType iso_node_get_type(IsoNode *node)
Definition: node.c:321
#define ISO_NON_MBR_SYS_AREA
Definition: libisofs.h:9078
int iso_stream_close(IsoStream *stream)
Definition: stream.c:804
#define ISO_ASSERT_FAILURE
Definition: libisofs.h:8737
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt,...)
Definition: messages.c:579
struct iso_file_section * sections
Definition: filesrc.h:56
int nsections
Definition: filesrc.h:57
Definition: node.h:149
Ecma119Image * target
Definition: writer.h:28
int(* write_data)(IsoImageWriter *writer)
Definition: writer.h:23
void * data
Definition: writer.h:27
int(* compute_data_blocks)(IsoImageWriter *writer)
Definition: writer.h:19
int(* write_vol_desc)(IsoImageWriter *writer)
Definition: writer.h:21
int(* free_data)(IsoImageWriter *writer)
Definition: writer.h:25
char * mips_boot_file_paths[15]
Definition: image.h:76
char * hppa_bootloader
Definition: image.h:88
int id
Definition: image.h:97
char * hppa_kernel_64
Definition: image.h:90
char * hppa_kernel_32
Definition: image.h:89
char * hppa_ramdisk
Definition: image.h:91
char * alpha_boot_image
Definition: image.h:94
char * hppa_cmdline
Definition: image.h:87
int num_mips_boot_files
Definition: image.h:75
Definition: node.h:100
int partition_heads_per_cyl
Definition: ecma119.h:788
int post_iso_part_pad
Definition: ecma119.h:865
int apm_req_flags
Definition: ecma119.h:853
uint32_t vol_space_size
Definition: ecma119.h:602
struct iso_mbr_partition_request * mbr_req[4]
Definition: ecma119.h:858
char * system_area_data
Definition: ecma119.h:702
int mbr_req_count
Definition: ecma119.h:859
IsoImage * image
Definition: ecma119.h:560
struct el_torito_boot_catalog * catalog
Definition: ecma119.h:685
int partition_secs_per_head
Definition: ecma119.h:786
uint32_t appended_part_size[8]
Definition: ecma119.h:825
uint32_t appended_part_prepad[8]
Definition: ecma119.h:823
uint32_t gpt_backup_end
Definition: ecma119.h:898
int num_bootsrc
Definition: ecma119.h:688
uint32_t gpt_max_entries
Definition: ecma119.h:900
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t part_align_blocks
Definition: ecma119.h:819
uint32_t mipsel_p_vaddr
Definition: ecma119.h:809
int gpt_backup_outside
Definition: ecma119.h:880
int system_area_options
Definition: ecma119.h:735
uint32_t gpt_part_start
Definition: ecma119.h:896
uint32_t prep_part_size
Definition: ecma119.h:867
uint8_t gpt_uuid_base[16]
Definition: ecma119.h:883
uint8_t sys_area_as_written[16 *2048]
Definition: ecma119.h:906
IsoImageWriter ** writers
Definition: ecma119.h:753
uint32_t mipsel_p_filesz
Definition: ecma119.h:810
int apm_req_count
Definition: ecma119.h:848
IsoFileSrc * efi_boot_part_filesrc
Definition: ecma119.h:888
uint32_t mipsel_p_offset
Definition: ecma119.h:808
int have_appended_partitions
Definition: ecma119.h:826
uint32_t gpt_uuid_counter
Definition: ecma119.h:885
uint32_t appended_part_start[8]
Definition: ecma119.h:824
struct iso_apm_partition_request * apm_req[63]
Definition: ecma119.h:847
size_t nwriters
Definition: ecma119.h:752
uint32_t curblock
Definition: ecma119.h:618
IsoFileSrc ** bootsrc
Definition: ecma119.h:689
uint32_t gpt_backup_size
Definition: ecma119.h:899
off_t total_size
Definition: ecma119.h:599
IsoFileSrc * sparc_core_src
Definition: ecma119.h:815
uint32_t mipsel_e_entry
Definition: ecma119.h:807
int gpt_is_computed
Definition: ecma119.h:901
int gpt_req_flags
Definition: ecma119.h:877
int hfsp_iso_block_fac
Definition: ecma119.h:840
int gpt_disk_guid_set
Definition: ecma119.h:894
uint8_t gpt_disk_guid[16]
Definition: ecma119.h:893
struct iso_gpt_partition_request * gpt_req[248]
Definition: ecma119.h:874
int pvd_size_is_total_size
Definition: ecma119.h:607
uint32_t efi_boot_part_size
Definition: ecma119.h:887
int gpt_req_count
Definition: ecma119.h:875
union ecma119_node::@0 info
IsoFileSrc * file
Definition: ecma119_tree.h:75
struct el_torito_boot_image * bootimages[32]
Definition: eltorito.h:46
unsigned int isolinux_options
Definition: eltorito.h:83
uint32_t size
Definition: libisofs.h:259
uint32_t block
Definition: libisofs.h:258
IsoImage * image
Definition: ecma119.c:1560
int iso_gpt_flag
Definition: ecma119.h:519
int appended_as_apm
Definition: ecma119.h:499
int part_like_isohybrid
Definition: ecma119.h:504
int prep_part_flag
Definition: ecma119.h:471
char * efi_boot_partition
Definition: ecma119.h:476
char ascii_disc_label[129]
Definition: ecma119.h:524
uint32_t ms_block
Definition: ecma119.h:379
uint32_t partition_offset
Definition: ecma119.h:451
uint32_t tail_blocks
Definition: ecma119.h:465
int iso_mbr_part_type
Definition: ecma119.h:512
uint8_t appended_part_types[8]
Definition: ecma119.h:484
int appended_as_gpt
Definition: ecma119.h:495
uint8_t appended_part_gpt_flags[8]
Definition: ecma119.h:491
char * prep_partition
Definition: ecma119.h:470
char * appended_partitions[8]
Definition: ecma119.h:483
unsigned int fat
Definition: ecma119.h:110
int apm_block_size
Definition: ecma119.h:537
int appended_part_flags[8]
Definition: ecma119.h:485
uint8_t iso_gpt_type_guid[16]
Definition: ecma119.h:516
uint8_t appended_part_type_guids[8][16]
Definition: ecma119.h:486
int efi_boot_part_flag
Definition: ecma119.h:477
int iso_read_mipsel_elf(Ecma119Image *t, int flag)
Definition: system_area.c:610
static int intvl_overlap(uint64_t start1, uint64_t end1, uint64_t start2, uint64_t end2, int second)
Definition: system_area.c:1668
static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
Definition: system_area.c:1449
int partappend_writer_create(Ecma119Image *target)
Definition: system_area.c:3279
static int cmp_partition_request(const void *f1, const void *f2)
Definition: system_area.c:1157
int iso_write_system_area(Ecma119Image *t, uint8_t *buf, int flag)
Definition: system_area.c:1881
static int gpt_tail_writer_free_data(IsoImageWriter *writer)
Definition: system_area.c:2981
static int gpt_tail_writer_write_data(IsoImageWriter *writer)
Definition: system_area.c:2906
int iso_align_isohybrid(Ecma119Image *t, int flag)
Definition: system_area.c:2303
static int partappend_writer_write_data(IsoImageWriter *writer)
Definition: system_area.c:3243
static int precompute_gpt(Ecma119Image *t)
Definition: system_area.c:2728
static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: system_area.c:3012
static int partappend_writer_write_vol_desc(IsoImageWriter *writer)
Definition: system_area.c:3237
static int partprepend_writer_write_data(IsoImageWriter *writer)
Definition: system_area.c:3162
int assess_appended_gpt(Ecma119Image *t, int flag)
Definition: system_area.c:2644
#define O_BINARY
Definition: system_area.c:47
static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size, struct iso_apm_partition_request *req, uint8_t *buf, int map_entries, int flag)
Definition: system_area.c:1184
static int hppa_palo_get_filepar(Ecma119Image *t, char *path, uint32_t *adr, uint32_t *len, int flag)
Definition: system_area.c:860
static int write_sun_partition_entry(int partition_number, char *appended_partitions[], uint32_t partition_offset[], uint32_t partition_size[], uint32_t cyl_size, uint8_t *buf, int flag)
Definition: system_area.c:745
void iso_delete_gpt_apm_fillers(Ecma119Image *target, int flag)
Definition: system_area.c:3304
static int partprepend_writer_free_data(IsoImageWriter *writer)
Definition: system_area.c:3194
int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_guid[16], uint8_t partition_guid[16], uint64_t flags, uint8_t name[72])
Definition: system_area.c:1083
int iso_quick_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, uint32_t start_block, uint32_t block_count, char *name, char *type)
Definition: system_area.c:1036
static int try_sph(off_t imgsize, int secs_per_head, int *heads_per_cyl, int flag)
Definition: system_area.c:2282
static int mbr_part_slot_is_unused(uint8_t *slot)
Definition: system_area.c:237
int gpt_tail_writer_create(Ecma119Image *target)
Definition: system_area.c:2987
static int rectify_apm(Ecma119Image *t)
Definition: system_area.c:1327
int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf, uint32_t max_entries, uint32_t part_start, uint32_t p_arr_crc)
Definition: system_area.c:1571
static int make_hppa_palo_sector(Ecma119Image *t, uint8_t *buf, int hdrversion, int flag)
Definition: system_area.c:901
static int make_sun_disk_label(Ecma119Image *t, uint8_t *buf, int flag)
Definition: system_area.c:790
static void iso_write_gpt_entry(Ecma119Image *t, uint8_t *buf, uint8_t type_guid[16], uint8_t part_uuid[16], uint64_t start_lba, uint64_t end_lba, uint64_t flags, uint8_t name[72])
Definition: system_area.c:1539
int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128], int *apm_count, int flag)
int partprepend_writer_create(Ecma119Image *target)
Definition: system_area.c:3200
uint32_t iso_crc32_gpt(unsigned char *data, int count, int flag)
Definition: system_area.c:2513
static int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc, uint8_t part_type, uint8_t *buf, int flag)
Definition: system_area.c:326
int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer)
Definition: system_area.c:2900
static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
Definition: system_area.c:1731
int iso_register_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, struct iso_apm_partition_request *req, int flag)
Definition: system_area.c:2439
static int write_mbr_partition_entry(int partition_number, int partition_type, uint64_t partition_offset, uint64_t partition_size, int sph, int hpc, uint8_t *buf, int flag)
Definition: system_area.c:254
int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t, int part_offset, int part_number, int fs_type, uint8_t *buf, int flag)
static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag)
Definition: system_area.c:495
static int iso_copy_apmhfs_to_gpt(Ecma119Image *t, int flag)
Definition: system_area.c:1684
int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, struct iso_mbr_partition_request *req, int flag)
Definition: system_area.c:2458
void iso_generate_gpt_guid(uint8_t guid[16])
Definition: system_area.c:2554
int iso_compute_append_partitions(Ecma119Image *t, int flag)
Definition: system_area.c:153
void iso_gpt_uuid(Ecma119Image *t, uint8_t uuid[16])
Definition: system_area.c:2626
int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: system_area.c:2871
static int partappend_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: system_area.c:3228
static int boot_nodes_from_iso_path(Ecma119Image *t, char *path, IsoNode **iso_node, Ecma119Node **ecma_node, char *purpose, int flag)
Definition: system_area.c:452
int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
void iso_ascii_utf_16le(uint8_t gap_name[72])
Definition: system_area.c:1657
static int partprepend_writer_write_vol_desc(IsoImageWriter *writer)
Definition: system_area.c:3156
static int make_dec_alpha_sector(Ecma119Image *t, uint8_t *buf, int flag)
Definition: system_area.c:1002
int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_byte, uint8_t status_byte, int desired_slot)
Definition: system_area.c:1108
int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array, int mbr_req_count, int slot)
Definition: system_area.c:1137
static int iso_offset_partition_start(uint32_t img_blocks, int post_part_pad, uint32_t partition_offset, int sph, int hpc, uint8_t *buf, int flag)
Definition: system_area.c:390
static void iso_compute_cyl_head_sec(uint64_t img_blocks, int hpc, int sph, uint32_t *end_lba, uint32_t *end_sec, uint32_t *end_head, uint32_t *end_cyl, int flag)
Definition: system_area.c:83
static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
Definition: system_area.c:1248
static int iso_find_gpt_entry(struct iso_gpt_partition_request **req_array, int gpt_req_count, uint64_t start_block, uint64_t block_count, int *index, int flag)
Definition: system_area.c:1062
static int compute_partition_size(Ecma119Image *t, char *disk_path, uint32_t *size, int flag)
Definition: system_area.c:115
static void iso_dummy_mbr_partition(uint8_t *buf, int mode)
Definition: system_area.c:1851
static int make_mipsel_boot_block(Ecma119Image *t, uint8_t *buf, int flag)
Definition: system_area.c:690
int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, struct iso_gpt_partition_request *req, int flag)
Definition: system_area.c:2476
void iso_mark_guid_version_4(uint8_t *u)
Definition: system_area.c:2540
static int partappend_writer_free_data(IsoImageWriter *writer)
Definition: system_area.c:3273
static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf, int flag)
Definition: system_area.c:1375
#define Libisofs_grub2_sparc_patch_size_poS
Definition: system_area.h:334
#define Libisofs_grub2_mbr_patch_offsT
Definition: system_area.h:328
#define Libisofs_grub2_mbr_patch_poS
Definition: system_area.h:327
#define Libisofs_grub2_sparc_patch_adr_poS
Definition: system_area.h:333