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)  

eltorito.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Vreixo Formoso
3  * Copyright (c) 2010 - 2016 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 "eltorito.h"
17 #include "fsource.h"
18 #include "filesrc.h"
19 #include "image.h"
20 #include "messages.h"
21 #include "writer.h"
22 #include "ecma119.h"
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 
28 /**
29  * This table should be written with the actual values at offset
30  * 8 of boot image, when used ISOLINUX boot loader
31  */
33  uint8_t bi_pvd BP(1, 4); /* LBA of primary volume descriptor */
34  uint8_t bi_file BP(5, 8); /* LBA of boot file */
35  uint8_t bi_length BP(9, 12); /* Length of boot file */
36  uint8_t bi_csum BP(13, 16); /* Checksum of boot file */
37  uint8_t bi_reserved BP(17, 56); /* Reserved */
38 };
39 
40 /**
41  * Structure for each one of the four entries in a partition table on a
42  * hard disk image.
43  */
45  uint8_t boot_ind;
46  uint8_t begin_chs[3];
47  uint8_t type;
48  uint8_t end_chs[3];
49  uint8_t start[4];
50  uint8_t size[4];
51 };
52 
53 /**
54  * Structures for a Master Boot Record of a hard disk image.
55  */
56 struct hard_disc_mbr {
57  uint8_t code_area[440];
58  uint8_t opt_disk_sg[4];
59  uint8_t pad[2];
60  struct partition_desc partition[4];
61  uint8_t sign1;
62  uint8_t sign2;
63 };
64 
65 /* API */
67 {
68  bootimg->platform_id = id;
69  return 1;
70 }
71 
72 /* API */
74 {
75  return bootimg->platform_id;
76 }
77 
78 /**
79  * Sets the load segment for the initial boot image. This is only for
80  * no emulation boot images, and is a NOP for other image types.
81  */
82 void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment)
83 {
84  if (bootimg->type != 0)
85  return;
86  if (segment < 0)
87  bootimg->load_seg = 0x1000 + segment;
88  else
89  bootimg->load_seg = segment;
90 }
91 
92 /* API */
94 {
95  return (int) bootimg->load_seg;
96 }
97 
98 /**
99  * Sets the number of sectors (512b) to be load at load segment during
100  * the initial boot procedure. This is only for no emulation boot images,
101  * and is a NOP for other image types.
102  */
103 void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors)
104 {
105  if (bootimg->type != 0)
106  return;
107  if (sectors < 0)
108  bootimg->load_size = 0x10000 + sectors;
109  else
110  bootimg->load_size = sectors;
111 }
112 
113 /* API */
115 {
116  return (int) bootimg->load_size;
117 }
118 
119 /* API */
121 {
122  if (bootimg->type != 0)
123  return;
124  bootimg->load_size_full= !!mode;
125 }
126 
127 /* API */
129 {
130  return bootimg->load_size_full;
131 }
132 
133 
134 /**
135  * Marks the specified boot image as not bootable
136  */
138 {
139  bootimg->bootable = 0;
140 }
141 
142 /* API */
144 {
145  return !!bootimg->bootable;
146 }
147 
148 /* API */
149 int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
150 {
151  memcpy(bootimg->id_string, id_string, 28);
152  return 1;
153 }
154 
155 /* API */
156 int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
157 {
158 
159  memcpy(id_string, bootimg->id_string, 28);
160  return 1;
161 }
162 
163 /* API */
164 int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
165 {
166  memcpy(bootimg->selection_crit, crit, 20);
167  return 1;
168 }
169 
170 /* API */
171 int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
172 {
173 
174  memcpy(crit, bootimg->selection_crit, 20);
175  return 1;
176 }
177 
178 /* API */
180 {
181  switch (flag & 15) {
182  case 0:
183  return bootimg->seems_boot_info_table;
184  case 1:
185  return bootimg->seems_grub2_boot_info;
186  }
187  return 0;
188 }
189 
190 /**
191  * Specifies that this image needs to be patched. This involves the writing
192  * of a 56 bytes boot information table at offset 8 of the boot image file.
193  * The original boot image file won't be modified.
194  * This is needed for isolinux boot images.
195  */
197 {
198  bootimg->isolinux_options |= 0x01;
199 }
200 
201 
202 /**
203  * Specifies options for IsoLinux boot images. This should only be used with
204  * isolinux boot images.
205  *
206  * @param options
207  * bitmask style flag. The following values are defined:
208  *
209  * bit 0 -> 1 to path the image, 0 to not
210  * Patching the image involves the writing of a 56 bytes
211  * boot information table at offset 8 of the boot image file.
212  * The original boot image file won't be modified. This is needed
213  * to allow isolinux images to be bootable.
214  * bit 1 -> 1 to generate an hybrid image, 0 to not
215  * An hybrid image is a boot image that boots from either CD/DVD
216  * media or from USB sticks. For that, you should use an isolinux
217  * image that supports hybrid mode. Recent images support this.
218  * @return
219  * 1 if success, < 0 on error
220  * @since 0.6.12
221  */
222 int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
223 {
224  bootimg->isolinux_options = (options & 0x03ff);
225  bootimg->seems_boot_info_table = !!(options & 1);
226  bootimg->seems_grub2_boot_info = !!(options & (1 << 9));
227  return ISO_SUCCESS;
228 }
229 
230 /* API */
232 {
233  return bootimg->isolinux_options & 0x03ff;
234 }
235 
236 /* API */
238  enum eltorito_boot_media_type *media_type)
239 {
240  if (bootimg) {
241  switch (bootimg->type) {
242  case 1:
243  case 2:
244  case 3:
245  *media_type = ELTORITO_FLOPPY_EMUL;
246  return 1;
247  case 4:
248  *media_type = ELTORITO_HARD_DISC_EMUL;
249  return 1;
250  case 0:
251  *media_type = ELTORITO_NO_EMUL;
252  return 1;
253  default:
254  /* should never happen */
255  return ISO_ASSERT_FAILURE;
256  break;
257  }
258  }
259  return ISO_WRONG_ARG_VALUE;
260 }
261 
262 static
263 int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
264 {
265  IsoBoot *node;
266  IsoNode **pos;
267  time_t now;
268  int ret;
269 
270  if (parent == NULL || name == NULL || boot == NULL) {
271  return ISO_NULL_POINTER;
272  }
273  if (boot) {
274  *boot = NULL;
275  }
276 
277  /* check if the name is valid */
278  ret = iso_node_is_valid_name(name);
279  if (ret < 0)
280  return ret;
281 
282  /* find place where to insert */
283  pos = &(parent->children);
284  while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
285  pos = &((*pos)->next);
286  }
287  if (*pos != NULL && !strcmp((*pos)->name, name)) {
288  /* a node with same name already exists */
290  }
291 
292  node = calloc(1, sizeof(IsoBoot));
293  if (node == NULL) {
294  return ISO_OUT_OF_MEM;
295  }
296 
297  node->node.refcount = 1;
298  node->node.type = LIBISO_BOOT;
299  node->node.name = strdup(name);
300  if (node->node.name == NULL) {
301  free(node);
302  return ISO_OUT_OF_MEM;
303  }
304  node->lba = 0;
305  node->size = 0;
306  node->content = NULL;
307 
308  /* attributes from parent */
309  node->node.mode = S_IFREG | (parent->node.mode & 0444);
310  node->node.uid = parent->node.uid;
311  node->node.gid = parent->node.gid;
312  node->node.hidden = parent->node.hidden;
313 
314  /* current time */
315  iso_nowtime(&now, 0);
316  node->node.atime = now;
317  node->node.ctime = now;
318  node->node.mtime = now;
319 
320  /* add to dir */
321  node->node.parent = parent;
322  node->node.next = *pos;
323  *pos = (IsoNode*)node;
324 
325  if (boot) {
326  *boot = node;
327  }
328  return ++parent->nchildren;
329 }
330 
331 /* Get start and size from "%d_start_%lus_size_%lud" */
332 static
333 void iso_parse_start_size(char *text, unsigned long *part_start,
334  unsigned long *part_size)
335 {
336  char *cpt;
337  unsigned long start, size;
338 
339  cpt = strchr(text, '_');
340  if (cpt == NULL)
341  return;
342  if (strncmp(cpt, "_start_", 7) != 0)
343  return;
344  sscanf(cpt + 7, "%lu", &start);
345  cpt = strchr(cpt + 7, '_');
346  if (cpt == NULL)
347  return;
348  if (*(cpt - 1) != 's')
349  return;
350  if (strncmp(cpt, "_size_", 6) != 0)
351  return;
352  sscanf(cpt + 6, "%lu", &size);
353  for (cpt = cpt + 6; *cpt >= '0' && *cpt <= '9'; cpt++);
354  if (*cpt != 'd')
355  return;
356 
357  *part_start = start;
358  *part_size = size;
359 }
360 
361 static
362 int create_image(IsoImage *image, const char *image_path,
364  struct el_torito_boot_image **bootimg,
365  IsoFile **bootnode)
366 {
367  int ret;
368  struct el_torito_boot_image *boot;
369  int boot_media_type = 0;
370  int load_sectors = 0; /* number of sector to load */
371  int part_idx = -1;
372  unsigned long part_start = 0, part_size = 0;
373  unsigned char partition_type = 0;
374  off_t size;
375  IsoNode *imgfile = NULL;
376  IsoStream *stream = NULL;
377 
378  *bootnode = NULL;
379 
380  if (strncmp(image_path, "--interval:appended_partition_", 30) == 0) {
381  /* --interval:appended_partition_N... */
382  if (type != ELTORITO_NO_EMUL) {
383 
384  /* >>> ??? lift this ban by making a temporary IsoStream from
385  partition source, determine size,
386  and read ELTORITO_HARD_DISC_EMUL MBR ?
387  */
388 
390  "Appended partition cannot serve as El Torito boot image with FD/HD emulation");
392  }
393  sscanf(image_path + 30, "%d", &part_idx);
394  if (part_idx < 1 || part_idx > ISO_MAX_PARTITIONS) {
396  "Appended partition index for El Torito boot image is out of range");
398  }
399  iso_parse_start_size((char *) (image_path + 30),
400  &part_start, &part_size);
401  part_idx--;
402  size = 1;
403  } else {
404  ret = iso_tree_path_to_node(image, image_path, &imgfile);
405  if (ret < 0) {
406  return ret;
407  }
408  if (ret == 0) {
410  "El Torito boot image file missing in ISO image: '%s'",
411  image_path);
412  return ISO_NODE_DOESNT_EXIST;
413  }
414 
415  if (imgfile->type != LIBISO_FILE) {
417  }
418  *bootnode = (IsoFile *) imgfile;
419 
420  stream = ((IsoFile*)imgfile)->stream;
421 
422  /* we need to read the image at least two times */
423  if (!iso_stream_is_repeatable(stream)) {
425  }
426 
427  size = iso_stream_get_size(stream);
428  }
429  if (size <= 0) {
431  "Boot image file is empty");
433  }
434 
435  switch (type) {
437  switch (size) {
438  case 1200 * 1024:
439  boot_media_type = 1; /* 1.2 meg diskette */
440  break;
441  case 1440 * 1024:
442  boot_media_type = 2; /* 1.44 meg diskette */
443  break;
444  case 2880 * 1024:
445  boot_media_type = 3; /* 2.88 meg diskette */
446  break;
447  default:
449  "Invalid image size %d Kb. Must be one of 1.2, 1.44"
450  "or 2.88 Mb", iso_stream_get_size(stream) / 1024);
452  break;
453  }
454  /* it seems that for floppy emulation we need to load
455  * a single sector (512b) */
456  load_sectors = 1;
457  break;
459  {
460  size_t i;
461  struct hard_disc_mbr mbr;
462  int used_partition;
463 
464  /* read the MBR on disc and get the type of the partition */
465  ret = iso_stream_open(stream);
466  if (ret < 0) {
468  "Can't open image file.");
469  return ret;
470  }
471  ret = iso_stream_read(stream, &mbr, sizeof(mbr));
472  iso_stream_close(stream);
473  if (ret != sizeof(mbr)) {
475  "Can't read MBR from image file.");
476  return ret < 0 ? ret : (int) ISO_FILE_READ_ERROR;
477  }
478 
479  /* check valid MBR signature */
480  if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
482  "Invalid MBR. Wrong signature.");
483  return (int) ISO_BOOT_IMAGE_NOT_VALID;
484  }
485 
486  /* ensure single partition */
487  used_partition = -1;
488  for (i = 0; i < 4; ++i) {
489  if (mbr.partition[i].type != 0) {
490  /* it's an used partition */
491  if (used_partition != -1) {
493  "Invalid MBR. At least 2 partitions: %d and "
494  "%d, are being used\n", used_partition, i);
496  } else
497  used_partition = i;
498  }
499  }
500  partition_type = mbr.partition[used_partition].type;
501  }
502  boot_media_type = 4;
503 
504  /* only load the MBR */
505  load_sectors = 1;
506  break;
507  case ELTORITO_NO_EMUL:
508  boot_media_type = 0;
509  break;
510  }
511 
512  boot = calloc(1, sizeof(struct el_torito_boot_image));
513  if (boot == NULL) {
514  return ISO_OUT_OF_MEM;
515  }
516  boot->image = (IsoFile*)imgfile;
517  boot->appended_idx = part_idx;
518  boot->appended_start = part_start;
519  boot->appended_size = part_size;
520  if (imgfile != NULL)
521  iso_node_ref(imgfile); /* get our ref */
522  boot->bootable = 1;
523  boot->seems_boot_info_table = 0;
524  boot->seems_grub2_boot_info = 0;
525  boot->seems_isohybrid_capable = 0;
526  boot->isolinux_options = 0;
527  boot->type = boot_media_type;
528  boot->partition_type = partition_type;
529  boot->load_seg = 0;
530  boot->load_size = load_sectors;
531  boot->load_size_full = 0;
532  boot->platform_id = 0; /* 80x86 */
533  memset(boot->id_string, 0, sizeof(boot->id_string));
534  memset(boot->selection_crit, 0, sizeof(boot->selection_crit));
535  *bootimg = boot;
536 
537  return ISO_SUCCESS;
538 }
539 
540 int iso_image_set_boot_image(IsoImage *image, const char *image_path,
541  enum eltorito_boot_media_type type,
542  const char *catalog_path,
543  ElToritoBootImage **boot)
544 {
545  int ret, i;
546  struct el_torito_boot_catalog *catalog;
547  ElToritoBootImage *boot_image= NULL;
548  IsoBoot *cat_node= NULL;
549  IsoFile *boot_node;
550 
551  if (image == NULL || image_path == NULL || catalog_path == NULL) {
552  return ISO_NULL_POINTER;
553  }
554  if (image->bootcat != NULL) {
556  }
557 
558  /* create the node for the catalog */
559  {
560  IsoDir *parent;
561  char *catdir = NULL, *catname = NULL;
562  catdir = strdup(catalog_path);
563  if (catdir == NULL) {
564  return ISO_OUT_OF_MEM;
565  }
566 
567  /* get both the dir and the name */
568  catname = strrchr(catdir, '/');
569  if (catname == NULL)
570  catname = catdir;
571  if (catname == catdir) {
572  /* we are appending catalog to root node */
573  parent = image->root;
574  } else {
575  IsoNode *p;
576  catname[0] = '\0';
577  ret = iso_tree_path_to_node(image, catdir, &p);
578  if (ret <= 0) {
580  "Cannot find directory for El Torito boot catalog in ISO image: '%s'",
581  catdir);
582  free(catdir);
583  return ret < 0 ? ret : (int) ISO_NODE_DOESNT_EXIST;
584  }
585  if (p->type != LIBISO_DIR) {
586  free(catdir);
587  return ISO_WRONG_ARG_VALUE;
588  }
589  parent = (IsoDir*)p;
590  }
591  if (catname[0] == '/' || catname[0] == 0)
592  catname++;
593  ret = iso_tree_add_boot_node(parent, catname, &cat_node);
594  free(catdir);
595  if (ret < 0) {
596  return ret;
597  }
598  }
599 
600  /* create the boot image */
601  ret = create_image(image, image_path, type, &boot_image, &boot_node);
602  if (ret < 0) {
603  goto boot_image_cleanup;
604  }
605 
606  /* creates the catalog with the given image */
607  catalog = calloc(1, sizeof(struct el_torito_boot_catalog));
608  if (catalog == NULL) {
609  ret = ISO_OUT_OF_MEM;
610  goto boot_image_cleanup;
611  }
612  catalog->num_bootimages = 1;
613  catalog->bootimages[0] = boot_image;
614  for (i = 1; i < Libisofs_max_boot_imageS; i++)
615  catalog->bootimages[i] = NULL;
616  catalog->node = cat_node;
617  catalog->sort_weight = 1000000000; /* very high */
618  if (boot_node != NULL)
619  if (!(boot_node->explicit_weight || boot_node->from_old_session))
620  boot_node->sort_weight = 2;
621  iso_node_ref((IsoNode*)cat_node);
622  image->bootcat = catalog;
623 
624  if (boot) {
625  *boot = boot_image;
626  }
627 
628  return ISO_SUCCESS;
629 
630 boot_image_cleanup:;
631  if (cat_node) {
632  iso_node_take((IsoNode*)cat_node);
633  iso_node_unref((IsoNode*)cat_node);
634  }
635  if (boot_image) {
636  if (boot_image->image != NULL)
637  iso_node_unref((IsoNode*)boot_image->image);
638  free(boot_image);
639  }
640  return ret;
641 }
642 
643 /**
644  * Get the boot catalog and the El-Torito default boot image of an ISO image.
645  *
646  * This can be useful, for example, to check if a volume read from a previous
647  * session or an existing image is bootable. It can also be useful to get
648  * the image and catalog tree nodes. An application would want those, for
649  * example, to prevent the user removing it.
650  *
651  * Both nodes are owned by libisofs and should not be freed. You can get your
652  * own ref with iso_node_ref(). You can can also check if the node is already
653  * on the tree by getting its parent (note that when reading El-Torito info
654  * from a previous image, the nodes might not be on the tree even if you haven't
655  * removed them). Remember that you'll need to get a new ref
656  * (with iso_node_ref()) before inserting them again to the tree, and probably
657  * you will also need to set the name or permissions.
658  *
659  * @param image
660  * The image from which to get the boot image.
661  * @param boot
662  * If not NULL, it will be filled with a pointer to the boot image, if
663  * any. That object is owned by the IsoImage and should not be freed by
664  * the user, nor dereferenced once the last reference to the IsoImage was
665  * disposed via iso_image_unref().
666  * @param imgnode
667  * When not NULL, it will be filled with the image tree node. No extra ref
668  * is added, you can use iso_node_ref() to get one if you need it.
669  * @param catnode
670  * When not NULL, it will be filled with the catnode tree node. No extra
671  * ref is added, you can use iso_node_ref() to get one if you need it.
672  * @return
673  * 1 on success, 0 is the image is not bootable (i.e., it has no El-Torito
674  * image), < 0 error.
675  */
677  IsoFile **imgnode, IsoBoot **catnode)
678 {
679  if (image == NULL) {
680  return ISO_NULL_POINTER;
681  }
682  if (image->bootcat == NULL) {
683  return 0;
684  }
685 
686  /* ok, image is bootable */
687  if (boot) {
688  *boot = image->bootcat->bootimages[0];
689  }
690  if (imgnode) {
691  *imgnode = image->bootcat->bootimages[0]->image;
692  }
693  if (catnode) {
694  *catnode = image->bootcat->node;
695  }
696  return ISO_SUCCESS;
697 }
698 
699 int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba,
700  char **content, off_t *size)
701 {
702  IsoBoot *bootcat;
703 
704  *catnode = NULL;
705  *lba = 0;
706  *content = NULL;
707  *size = 0;
708  bootcat = image->bootcat->node;
709  if (bootcat == NULL)
710  return 0;
711  *catnode = bootcat;
712  *lba = bootcat->lba;
713  if (bootcat->size > 0 && bootcat->content != NULL) {
714  *content = calloc(1, bootcat->size);
715  if (*content == NULL)
716  return ISO_OUT_OF_MEM;
717  memcpy(*content, bootcat->content, bootcat->size);
718  }
719  if (*content != NULL)
720  *size = bootcat->size;
721  return 1;
722 }
723 
724 int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
725  ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
726 {
727  int i;
728  struct el_torito_boot_catalog *cat;
729 
730  if (image == NULL)
731  return ISO_NULL_POINTER;
732  if (image->bootcat == NULL)
733  return 0;
734  cat = image->bootcat;
735  *num_boots = cat->num_bootimages;
736  *boots = NULL;
737  *bootnodes = NULL;
738  if (*num_boots <= 0)
739  return 0;
740  *boots = calloc(*num_boots, sizeof(ElToritoBootImage *));
741  *bootnodes = calloc(*num_boots, sizeof(IsoFile *));
742  if(*boots == NULL || *bootnodes == NULL) {
743  if (*boots != NULL)
744  free(*boots);
745  if (*bootnodes != NULL)
746  free(*bootnodes);
747  *boots = NULL;
748  *bootnodes = NULL;
749  return ISO_OUT_OF_MEM;
750  }
751  for (i = 0; i < *num_boots; i++) {
752  (*boots)[i] = cat->bootimages[i];
753  (*bootnodes)[i] = image->bootcat->bootimages[i]->image;
754  }
755  return 1;
756 }
757 
758 /**
759  * Removes the El-Torito bootable image.
760  *
761  * The IsoBoot node that acts as placeholder for the catalog is also removed
762  * for the image tree, if there.
763  * If the image is not bootable (don't have el-torito boot image) this function
764  * just returns.
765  */
767 {
768  if (image == NULL || image->bootcat == NULL)
769  return;
770 
771  /*
772  * remove catalog node from its parent and dispose it
773  * (another reference is with the catalog)
774  */
775  if (iso_node_get_parent((IsoNode*) image->bootcat->node) != NULL) {
776  iso_node_take((IsoNode*) image->bootcat->node);
777  iso_node_unref((IsoNode*) image->bootcat->node);
778  }
779 
780  /* free boot catalog and image, including references to nodes */
782  image->bootcat = NULL;
783 }
784 
785 /* API */
786 int iso_image_add_boot_image(IsoImage *image, const char *image_path,
787  enum eltorito_boot_media_type type, int flag,
788  ElToritoBootImage **boot)
789 {
790  int ret;
791  struct el_torito_boot_catalog *catalog = image->bootcat;
792  ElToritoBootImage *boot_img;
793  IsoFile *boot_node;
794 
795  if(catalog == NULL)
796  return ISO_BOOT_NO_CATALOG;
799  ret = create_image(image, image_path, type, &boot_img, &boot_node);
800  if (ret < 0)
801  return ret;
802  if (boot_node != NULL)
803  if (!(boot_node->explicit_weight || boot_node->from_old_session))
804  boot_node->sort_weight = 2;
805  catalog->bootimages[catalog->num_bootimages] = boot_img;
806  catalog->num_bootimages++;
807  if (boot != NULL)
808  *boot = boot_img;
809  return 1;
810 }
811 
812 /* API */
814 {
815  if (image->bootcat == NULL)
816  return 0;
817  image->bootcat->sort_weight = sort_weight;
818  return 1;
819 }
820 
821 /* API */
822 int iso_image_set_boot_catalog_hidden(IsoImage *image, int hide_attrs)
823 {
824  if (image->bootcat == NULL)
825  return 0;
826  if (image->bootcat->node == NULL)
827  return 0;
828  iso_node_set_hidden((IsoNode *) image->bootcat->node, hide_attrs);
829  return 1;
830 }
831 
832 
834 {
835  struct el_torito_boot_image *image;
836  int i;
837 
838  if (cat == NULL) {
839  return;
840  }
841 
842  for (i = 0; i < Libisofs_max_boot_imageS; i++) {
843  image = cat->bootimages[i];
844  if (image == NULL)
845  continue;
846  if ((IsoNode*)image->image != NULL)
847  iso_node_unref((IsoNode*)image->image);
848  free(image);
849  }
850  if ((IsoNode*)cat->node != NULL)
851  iso_node_unref((IsoNode*)cat->node);
852  free(cat);
853 }
854 
855 /**
856  * Stream that generates the contents of a El-Torito catalog.
857  */
859 {
861  uint8_t buffer[BLOCK_SIZE];
862  int offset; /* -1 if stream is not opened */
863 };
864 
865 static void
866 write_validation_entry(uint8_t *buf, uint8_t platform_id,
867  uint8_t id_string[24])
868 {
869  size_t i;
870  int checksum;
871 
872  struct el_torito_validation_entry *ve =
873  (struct el_torito_validation_entry*)buf;
874  ve->header_id[0] = 1;
875  ve->platform_id[0] = platform_id;
876  memcpy(ve->id_string, id_string, sizeof(ve->id_string));
877  ve->key_byte1[0] = 0x55;
878  ve->key_byte2[0] = 0xAA;
879  /* calculate the checksum, to ensure sum of all words is 0 */
880  checksum = 0;
881  for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) {
882  checksum -= (int16_t) ((buf[i+1] << 8) | buf[i]);
883  }
884  iso_lsb(ve->checksum, checksum, 2);
885 }
886 
887 static void
888 write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
889 {
890  char *id_string;
891 
892  struct el_torito_section_header *e =
893  (struct el_torito_section_header *) buf;
894 
895  /* 0x90 = more section headers follow , 0x91 = final section */
896  e->header_indicator[0] =
897  0x90 + (idx == t->catalog->num_bootimages - num_entries);
898  e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
899  e->num_entries[0] = num_entries & 0xff;
900  e->num_entries[1] = (num_entries >> 8) & 0xff;;
901  id_string = (char *) e->id_string;
902  memcpy(id_string, t->catalog->bootimages[idx]->id_string,
903  sizeof(e->id_string));
904 }
905 
906 static int
908  struct el_torito_section_entry *se,
909  uint16_t load_size, off_t full_byte_size, int flag)
910 {
911  uint16_t size;
912  off_t blocks;
913 
914  size= load_size;
915  if(img->type == 0 && img->load_size_full) {
916  blocks= ((full_byte_size + 2047) / 2048) * 4;
917  if (blocks > 65535) {
918  if (img->platform_id == 0xef)
919  size= 0;
920  else
921  size= 65535;
922  } else if(blocks <= 0) {
923  size= 1;
924  } else {
925  size= blocks;
926  }
927  }
928  iso_lsb(se->sec_count, size, 2);
929  return(1);
930 }
931 
932 /**
933  * Write one section entry.
934  * Usable for the Default Entry
935  * and for Section Entries with Selection criteria type == 0
936  */
937 static
938 int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
939 {
940  struct el_torito_boot_image *img;
941  struct el_torito_section_entry *se =
942  (struct el_torito_section_entry*)buf;
943  int app_idx, mode = 0;
944 
945  img = t->catalog->bootimages[idx];
946 
947  se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
948  se->boot_media_type[0] = img->type;
949  iso_lsb(se->load_seg, img->load_seg, 2);
950  se->system_type[0] = img->partition_type;
951 
952  if (t->boot_appended_idx[idx] >= 0)
953  if (t->appended_part_size[t->boot_appended_idx[idx]] > 0)
954  mode = 2; /* appended partition */
955  if (mode == 0 && t->opts->appendable &&
956  (t->boot_intvl_start[idx] > 0 || t->boot_intvl_size[idx] > 0) &&
957  t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 <=
958  t->opts->ms_block)
959  mode = 1; /* image interval */
960  if (mode == 0 && t->boot_appended_idx[idx] >= 0) {
962  "Appended partition which shall serve as boot image does not exist");
964  }
965 
966  if (mode == 1) {
967  if (t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 >
968  t->total_size / 2048 + t->opts->ms_block - t->eff_partition_offset
969  ) {
971  "Block interval which shall serve as boot image is outside result range");
973  }
974 
975  /* >>> check for non-automatic load size */;
976 
977  if (t->boot_intvl_size[idx] > 65535) {
978  if (img->platform_id == 0xef)
979  iso_lsb(se->sec_count, 0, 2);
980  else
981  iso_lsb(se->sec_count, 65535, 2);
982  } else {
983  if (t->boot_intvl_size[idx] == 0) {
985  "Block interval which shall serve as boot image has zero size");
987  }
988  iso_lsb(se->sec_count, t->boot_intvl_size[idx], 2);
989  }
990  iso_lsb(se->block, t->boot_intvl_start[idx], 4);
991  } else if (mode == 2) {
992  app_idx = t->boot_appended_idx[idx];
993 
994  /* >>> check for non-automatic load size */;
995 
996  if (t->appended_part_size[app_idx] * 4 > 65535) {
997  if (img->platform_id == 0xef)
998  iso_lsb(se->sec_count, 0, 2);
999  else
1000  iso_lsb(se->sec_count, 65535, 2);
1001  } else {
1002  iso_lsb(se->sec_count, t->appended_part_size[app_idx] * 4, 2);
1003  }
1004  iso_lsb(se->block, t->appended_part_start[app_idx], 4);
1005  } else {
1006  write_section_load_size(img, se, (uint16_t) img->load_size,
1007  (off_t) t->bootsrc[idx]->sections[0].size, 0);
1008  iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4);
1009  }
1010 
1011  se->selec_criteria[0] = img->selection_crit[0];
1012  memcpy(se->vendor_sc, img->selection_crit + 1, 19);
1013  return ISO_SUCCESS;
1014 }
1015 
1016 static
1018 {
1019  int i, j, k, num_entries, ret;
1020  struct catalog_stream *data;
1021  uint8_t *wpt;
1022  struct el_torito_boot_catalog *cat;
1023  struct el_torito_boot_image **boots;
1024 
1025  if (stream == NULL) {
1026  return ISO_NULL_POINTER;
1027  }
1028  data = stream->data;
1029  cat = data->target->catalog;
1030  boots = cat->bootimages;
1031 
1032  if (data->offset != -1) {
1033  return ISO_FILE_ALREADY_OPENED;
1034  }
1035 
1036  memset(data->buffer, 0, BLOCK_SIZE);
1037 
1038  /* fill the buffer with the catalog contents */
1040  boots[0]->platform_id, boots[0]->id_string);
1041 
1042  /* write default entry = first boot image */
1043  ret = write_section_entry(data->buffer + 32, data->target, 0);
1044  if (ret < 0)
1045  return ret;
1046 
1047  /* IMPORTANT: The maximum number of boot images must fit into BLOCK_SIZE */
1048  wpt = data->buffer + 64;
1049  for (i = 1; i < cat->num_bootimages; ) {
1050  /* Look ahead and put images of same platform_id and id_string
1051  into the same section */
1052  for (j = i + 1; j < cat->num_bootimages; j++) {
1053  if (boots[i]->platform_id != boots[j]->platform_id)
1054  break;
1055  for (k = 0; k < (int) sizeof(boots[i]->id_string); k++)
1056  if (boots[i]->id_string[k] != boots[j]->id_string[k])
1057  break;
1058  if (k < (int) sizeof(boots[i]->id_string))
1059  break;
1060  }
1061  num_entries = j - i;
1062 
1063  write_section_header(wpt, data->target, i, num_entries);
1064  wpt += 32;
1065  for (j = 0; j < num_entries; j++) {
1066  ret = write_section_entry(wpt, data->target, i);
1067  if (ret < 0)
1068  return ret;
1069  wpt += 32;
1070  i++;
1071  }
1072  }
1073  data->offset = 0;
1074  return ISO_SUCCESS;
1075 }
1076 
1077 static
1079 {
1080  struct catalog_stream *data;
1081  if (stream == NULL) {
1082  return ISO_NULL_POINTER;
1083  }
1084  data = stream->data;
1085 
1086  if (data->offset == -1) {
1087  return ISO_FILE_NOT_OPENED;
1088  }
1089  data->offset = -1;
1090  return ISO_SUCCESS;
1091 }
1092 
1093 static
1095 {
1096  return BLOCK_SIZE;
1097 }
1098 
1099 static
1100 int catalog_read(IsoStream *stream, void *buf, size_t count)
1101 {
1102  size_t len;
1103  struct catalog_stream *data;
1104  if (stream == NULL || buf == NULL) {
1105  return ISO_NULL_POINTER;
1106  }
1107  if (count == 0) {
1108  return ISO_WRONG_ARG_VALUE;
1109  }
1110  data = stream->data;
1111 
1112  if (data->offset == -1) {
1113  return ISO_FILE_NOT_OPENED;
1114  }
1115 
1116  len = MIN(count, (size_t) (BLOCK_SIZE - data->offset));
1117  memcpy(buf, data->buffer + data->offset, len);
1118  return len;
1119 }
1120 
1121 static
1123 {
1124  return 1;
1125 }
1126 
1127 /**
1128  * fs_id will be the id reserved for El-Torito
1129  * dev_id will be 0 for catalog, 1 for boot image (if needed)
1130  * ino_id 0 is supposed to be unique. At write time it will get assigned
1131  * an automatic file serial number in the ISO, if needed.
1132  */
1133 static
1134 void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
1135  ino_t *ino_id)
1136 {
1137  *fs_id = ISO_ELTORITO_FS_ID;
1138  *dev_id = 0;
1139  *ino_id = 0;
1140 }
1141 
1142 static
1144 {
1145  free(stream->data);
1146 }
1147 
1149  0,
1150  "boot",
1151  catalog_open,
1152  catalog_close,
1154  catalog_read,
1157  catalog_free,
1158  NULL,
1159  NULL,
1160  NULL,
1161  NULL
1162 };
1163 
1164 /**
1165  * Create an IsoStream for writing El-Torito catalog for a given target.
1166  */
1167 static
1169 {
1170  IsoStream *str;
1171  struct catalog_stream *data;
1172 
1173  if (target == NULL || stream == NULL || target->catalog == NULL) {
1174  return ISO_NULL_POINTER;
1175  }
1176 
1177  str = calloc(1, sizeof(IsoStream));
1178  if (str == NULL) {
1179  return ISO_OUT_OF_MEM;
1180  }
1181  data = calloc(1, sizeof(struct catalog_stream));
1182  if (data == NULL) {
1183  free(str);
1184  return ISO_OUT_OF_MEM;
1185  }
1186 
1187  /* fill data */
1188  data->target = target;
1189  data->offset = -1;
1190 
1191  str->refcount = 1;
1192  str->data = data;
1193  str->class = &catalog_stream_class;
1194 
1195  *stream = str;
1196  return ISO_SUCCESS;
1197 }
1198 
1200 {
1201  int ret;
1202  IsoFileSrc *file;
1203  IsoStream *stream;
1204 
1205  if (target == NULL || src == NULL || target->catalog == NULL) {
1206  return ISO_OUT_OF_MEM;
1207  }
1208 
1209  if (target->cat != NULL) {
1210  /* catalog file src already created */
1211  *src = target->cat;
1212  return ISO_SUCCESS;
1213  }
1214 
1215  file = calloc(1, sizeof(IsoFileSrc));
1216  if (file == NULL) {
1217  return ISO_OUT_OF_MEM;
1218  }
1219 
1220  ret = catalog_stream_new(target, &stream);
1221  if (ret < 0) {
1222  free(file);
1223  return ret;
1224  }
1225 
1226  /* fill fields */
1227  file->no_write = 0; /* TODO allow copy of old img catalog???? */
1228  file->checksum_index = 0;
1229  file->nsections = 1;
1230  file->sections = calloc(1, sizeof(struct iso_file_section));
1232  file->stream = stream;
1233 
1234  ret = iso_file_src_add(target, file, src);
1235  if (ret <= 0) {
1236  iso_stream_unref(stream);
1237  free(file);
1238  } else {
1239  target->cat = *src;
1240  }
1241  return ret;
1242 }
1243 
1244 /******************* EL-TORITO WRITER *******************************/
1245 
1246 /**
1247  * Insert boot info table content into buf.
1248  *
1249  * @return
1250  * 1 on success, 0 error (but continue), < 0 error
1251  */
1252 int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
1253  uint32_t boot_lba, uint32_t imgsize)
1254 {
1255  struct boot_info_table *info;
1256  uint32_t checksum;
1257  uint32_t offset;
1258 
1259  info = (struct boot_info_table *) (buf + 8);
1260  if (imgsize < 64)
1261  return ISO_ISOLINUX_CANT_PATCH;
1262 
1263  /* compute checksum, as the the sum of all 32 bit words in boot image
1264  * from offset 64 */
1265  checksum = 0;
1266  offset = 64;
1267 
1268  while (offset <= imgsize - 4) {
1269  checksum += iso_read_lsb(buf + offset, 4);
1270  offset += 4;
1271  }
1272  if (offset != imgsize) {
1273  /*
1274  * file length not multiple of 4
1275  * empty space in isofs is padded with zero;
1276  * assume same for last dword
1277  */
1278  checksum += iso_read_lsb(buf + offset, imgsize - offset);
1279  }
1280 
1281  /*memset(info, 0, sizeof(struct boot_info_table));*/
1282  iso_lsb(info->bi_pvd, pvd_lba, 4);
1283  iso_lsb(info->bi_file, boot_lba, 4);
1284  iso_lsb(info->bi_length, imgsize, 4);
1285  iso_lsb(info->bi_csum, checksum, 4);
1286  memset(buf + 24, 0, 40);
1287  return ISO_SUCCESS;
1288 }
1289 
1290 /**
1291  * Patch an El Torito boot image by a boot info table.
1292  *
1293  * @return
1294  * 1 on success, 0 error (but continue), < 0 error
1295  */
1296 static
1298  size_t imgsize, int idx)
1299 {
1300  int ret;
1301 
1302  if (imgsize < 64) {
1304  "Isolinux image too small. We won't patch it.");
1305  }
1306  if (t->bootsrc[idx] == NULL)
1308  "Cannot apply ISOLINUX patching outside of ISO 9660 filesystem.");
1309  ret = make_boot_info_table(buf, t->opts->ms_block + (uint32_t) 16,
1310  t->bootsrc[idx]->sections[0].block,
1311  (uint32_t) imgsize);
1312  return ret;
1313 }
1314 
1315 
1316 /**
1317  * Patch a GRUB2 El Torito boot image.
1318  */
1319 static
1321  size_t imgsize, int idx,
1322  size_t pos, int offst)
1323 {
1324  uint64_t blk;
1325 
1326  if (imgsize < pos + 8)
1328  "Boot image too small for GRUB2. Will not patch it.");
1329  if (t->bootsrc[idx] == NULL)
1331  "Cannot apply GRUB2 patching outside of ISO 9660 filesystem.");
1332  blk = ((uint64_t) t->bootsrc[idx]->sections[0].block) * 4 + offst;
1333  iso_lsb((buf + pos), blk & 0xffffffff, 4);
1334  iso_lsb((buf + pos + 4), blk >> 32, 4);
1335  return ISO_SUCCESS;
1336 }
1337 
1338 
1339 /* Patch the boot images if indicated */
1341 {
1342  int ret, idx;
1343  size_t size;
1344  uint8_t *buf;
1345  IsoStream *new = NULL;
1346  IsoStream *original = NULL;
1347 
1348  if (t->catalog == NULL)
1349  return ISO_SUCCESS;
1350 
1351  for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
1352  if (!(t->catalog->bootimages[idx]->isolinux_options & 0x201))
1353  continue;
1354  if (t->bootsrc[idx] == NULL)
1356  "Cannot apply boot image patching outside of ISO 9660 filesystem");
1357 
1358  original = t->bootsrc[idx]->stream;
1359  size = (size_t) iso_stream_get_size(original);
1360  if (size > Libisofs_elto_max_patchablE)
1361  return ISO_PATCH_OVERSIZED_BOOT;
1362  if (iso_stream_get_input_stream(original, 0) != NULL)
1363  return ISO_PATCH_FILTERED_BOOT;
1364  buf = calloc(1, size);
1365  if (buf == NULL) {
1366  return ISO_OUT_OF_MEM;
1367  }
1368  ret = iso_stream_open(original);
1369  if (ret < 0) {
1370  free(buf);
1371  return ret;
1372  }
1373  ret = iso_stream_read(original, buf, size);
1374  iso_stream_close(original);
1375  if (ret != (int) size) {
1376  if (ret >= 0)
1378  "Cannot read all bytes from El Torito boot image for boot info table");
1379  return (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR;
1380  }
1381 
1382  /* ok, patch the read buffer */
1383  if (t->catalog->bootimages[idx]->isolinux_options & 0x200) {
1384  /* GRUB2 boot provisions */
1385  ret = patch_grub2_boot_image(buf, t, size, idx,
1388  if (ret < 0)
1389  return ret;
1390  }
1391  /* Must be done as last patching */
1392  if (t->catalog->bootimages[idx]->isolinux_options & 0x01) {
1393  /* Boot Info Table */
1394  ret = patch_boot_info_table(buf, t, size, idx);
1395  if (ret < 0)
1396  return ret;
1397  }
1398 
1399  /* replace the original stream with a memory stream that reads from
1400  * the patched buffer */
1401  ret = iso_memory_stream_new(buf, size, &new);
1402  if (ret < 0) {
1403  return ret;
1404  }
1405  t->bootsrc[idx]->stream = new;
1406  iso_stream_unref(original);
1407  }
1408  return ISO_SUCCESS;
1409 }
1410 
1411 static
1413 {
1414  /*
1415  * We have nothing to write.
1416  */
1417  return ISO_SUCCESS;
1418 }
1419 
1420 
1421 /**
1422  * Write the Boot Record Volume Descriptor (ECMA-119, 8.2)
1423  */
1424 static
1426 {
1427  Ecma119Image *t;
1428  struct ecma119_boot_rec_vol_desc vol;
1429 
1430  if (writer == NULL) {
1431  return ISO_NULL_POINTER;
1432  }
1433 
1434  t = writer->target;
1435  iso_msg_debug(t->image->id, "Write El-Torito boot record");
1436 
1437  memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
1438  vol.vol_desc_type[0] = 0;
1439  memcpy(vol.std_identifier, "CD001", 5);
1440  vol.vol_desc_version[0] = 1;
1441  memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23);
1442  iso_lsb(vol.boot_catalog,
1443  t->cat->sections[0].block - t->eff_partition_offset, 4);
1444  return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc));
1445 }
1446 
1447 static
1449 {
1450  /* nothing to do, the files are written by the file writer */
1451  return ISO_SUCCESS;
1452 }
1453 
1454 static
1456 {
1457  /* nothing to do */
1458  return ISO_SUCCESS;
1459 }
1460 
1462 {
1463  int ret, idx, outsource_efi = 0;
1464  IsoImageWriter *writer;
1465  IsoFile *bootimg = NULL;
1466  IsoFileSrc *src = NULL;
1467 
1468  writer = calloc(1, sizeof(IsoImageWriter));
1469  if (writer == NULL) {
1470  return ISO_OUT_OF_MEM;
1471  }
1472 
1477  writer->data = NULL;
1478  writer->target = target;
1479 
1480  /* add this writer to image */
1481  target->writers[target->nwriters++] = writer;
1482 
1483  /*
1484  * get catalog and image file sources.
1485  * Note that the catalog may be already added, when creating the low
1486  * level ECMA-119 tree.
1487  */
1488  if (target->cat == NULL) {
1489  ret = el_torito_catalog_file_src_create(target, &src);
1490  if (ret < 0) {
1491  return ret;
1492  }
1493  }
1494 
1495  if (target->opts->efi_boot_partition != NULL)
1496  if (strcmp(target->opts->efi_boot_partition, "--efi-boot-image") == 0)
1497  outsource_efi = 1;
1498  for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
1499  target->bootsrc[idx] = NULL;
1500  if (target->catalog->bootimages[idx]->appended_idx >= 0) {
1501  /* Use an appended partition as boot image rather than IsoFile */
1502  target->boot_appended_idx[idx] =
1503  target->catalog->bootimages[idx]->appended_idx;
1504  target->boot_intvl_start[idx] =
1505  target->catalog->bootimages[idx]->appended_start;
1506  target->boot_intvl_size[idx] =
1507  target->catalog->bootimages[idx]->appended_size;
1508  continue;
1509  }
1510 
1511  bootimg = target->catalog->bootimages[idx]->image;
1512  ret = iso_file_src_create(target, bootimg, &src);
1513  if (ret < 0) {
1514  return ret;
1515  }
1516  target->bootsrc[idx] = src;
1517 
1518  /* For patching an image, it needs to be copied always */
1519  if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
1520  src->no_write = 0;
1521  }
1522 
1523  /* If desired: Recognize first EFI boot image that will be newly
1524  written, and mark it as claimed for being a partition.
1525  */
1526  if (outsource_efi &&
1527  target->catalog->bootimages[idx]->platform_id == 0xef &&
1528  src->no_write == 0) {
1529  target->efi_boot_part_filesrc = src;
1530  src->sections[0].block = 0xfffffffe;
1531  ((IsoNode *) bootimg)->hidden |=
1533  outsource_efi = 0;
1534  }
1535  }
1536 
1537  /* we need the bootable volume descriptor */
1538  target->curblock++;
1539 
1540  if (outsource_efi) {
1541  /* Disable EFI Boot partition and complain */
1542  free(target->opts->efi_boot_partition);
1543  target->opts->efi_boot_partition = NULL;
1545 "No newly added El Torito EFI boot image found for exposure as GPT partition");
1546  return ISO_BOOT_NO_EFI_ELTO;
1547  }
1548 
1549  return ISO_SUCCESS;
1550 }
1551 
#define BLOCK_SIZE
Definition: buffer.h:23
int iso_write(Ecma119Image *target, void *buf, size_t count)
Definition: ecma119.c:3471
#define ISO_MAX_PARTITIONS
Definition: ecma119.h:47
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots, ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
Definition: eltorito.c:724
static int catalog_is_repeatable(IsoStream *stream)
Definition: eltorito.c:1122
int eltorito_writer_create(Ecma119Image *target)
Definition: eltorito.c:1461
int iso_image_set_boot_catalog_hidden(IsoImage *image, int hide_attrs)
Definition: eltorito.c:822
static int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
Definition: eltorito.c:1425
int iso_image_add_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, int flag, ElToritoBootImage **boot)
Definition: eltorito.c:786
static int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
Definition: eltorito.c:938
static int catalog_stream_new(Ecma119Image *target, IsoStream **stream)
Definition: eltorito.c:1168
int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id)
Definition: eltorito.c:66
int iso_image_set_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, const char *catalog_path, ElToritoBootImage **boot)
Definition: eltorito.c:540
static off_t catalog_get_size(IsoStream *stream)
Definition: eltorito.c:1094
int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg)
Definition: eltorito.c:73
static int patch_boot_info_table(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
Definition: eltorito.c:1297
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba, uint32_t boot_lba, uint32_t imgsize)
Definition: eltorito.c:1252
int el_torito_get_boot_media_type(ElToritoBootImage *bootimg, enum eltorito_boot_media_type *media_type)
Definition: eltorito.c:237
int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
Definition: eltorito.c:149
static int catalog_read(IsoStream *stream, void *buf, size_t count)
Definition: eltorito.c:1100
static void catalog_free(IsoStream *stream)
Definition: eltorito.c:1143
static int create_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, struct el_torito_boot_image **bootimg, IsoFile **bootnode)
Definition: eltorito.c:362
static int eltorito_writer_write_data(IsoImageWriter *writer)
Definition: eltorito.c:1448
static int patch_grub2_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx, size_t pos, int offst)
Definition: eltorito.c:1320
int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, IsoFile **imgnode, IsoBoot **catnode)
Definition: eltorito.c:676
int el_torito_get_full_load(ElToritoBootImage *bootimg)
Definition: eltorito.c:128
int el_torito_get_load_seg(ElToritoBootImage *bootimg)
Definition: eltorito.c:93
int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
Definition: eltorito.c:171
int iso_patch_eltoritos(Ecma119Image *t)
Definition: eltorito.c:1340
static int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: eltorito.c:1412
void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment)
Definition: eltorito.c:82
int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
Definition: eltorito.c:164
static void iso_parse_start_size(char *text, unsigned long *part_start, unsigned long *part_size)
Definition: eltorito.c:333
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
Definition: eltorito.c:833
static int eltorito_writer_free_data(IsoImageWriter *writer)
Definition: eltorito.c:1455
int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
Definition: eltorito.c:156
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
Definition: eltorito.c:231
int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight)
Definition: eltorito.c:813
void el_torito_set_no_bootable(ElToritoBootImage *bootimg)
Definition: eltorito.c:137
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag)
Definition: eltorito.c:179
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
Definition: eltorito.c:1199
int el_torito_get_bootable(ElToritoBootImage *bootimg)
Definition: eltorito.c:143
void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
Definition: eltorito.c:196
int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba, char **content, off_t *size)
Definition: eltorito.c:699
IsoStreamIface catalog_stream_class
Definition: eltorito.c:1148
int el_torito_get_load_size(ElToritoBootImage *bootimg)
Definition: eltorito.c:114
void el_torito_set_full_load(ElToritoBootImage *bootimg, int mode)
Definition: eltorito.c:120
void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors)
Definition: eltorito.c:103
static void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id)
Definition: eltorito.c:1134
void iso_image_remove_boot_image(IsoImage *image)
Definition: eltorito.c:766
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
Definition: eltorito.c:222
static int write_section_load_size(struct el_torito_boot_image *img, struct el_torito_section_entry *se, uint16_t load_size, off_t full_byte_size, int flag)
Definition: eltorito.c:907
static void write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
Definition: eltorito.c:888
static int catalog_open(IsoStream *stream)
Definition: eltorito.c:1017
static int catalog_close(IsoStream *stream)
Definition: eltorito.c:1078
static void write_validation_entry(uint8_t *buf, uint8_t platform_id, uint8_t id_string[24])
Definition: eltorito.c:866
static int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
Definition: eltorito.c:263
#define Libisofs_max_boot_imageS
Definition: eltorito.h:40
#define Libisofs_grub2_elto_patch_poS
Definition: eltorito.h:180
#define Libisofs_elto_max_patchablE
Definition: eltorito.h:188
#define Libisofs_grub2_elto_patch_offsT
Definition: eltorito.h:181
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
Definition: filesrc.c:69
int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
Definition: filesrc.c:192
#define ISO_ELTORITO_FS_ID
Definition: fsource.h:23
#define BP(a, b)
Definition: isofs_wrap.c:38
static uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
Definition: isofs_wrap.c:78
void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1478
#define MIN(a, b)
Definition: util.h:35
#define ISO_IMAGE_ALREADY_BOOTABLE
Definition: libisofs.h:8777
#define ISO_BOOT_IMAGE_OVERFLOW
Definition: libisofs.h:8783
#define ISO_PATCH_FILTERED_BOOT
Definition: libisofs.h:9204
#define ISO_BOOT_IMAGE_NOT_VALID
Definition: libisofs.h:8780
void iso_node_unref(IsoNode *node)
Definition: node.c:56
#define ISO_SUCCESS
Definition: libisofs.h:8719
eltorito_boot_media_type
Definition: libisofs.h:334
@ ELTORITO_HARD_DISC_EMUL
Definition: libisofs.h:336
@ ELTORITO_FLOPPY_EMUL
Definition: libisofs.h:335
@ ELTORITO_NO_EMUL
Definition: libisofs.h:337
@ LIBISO_BOOT
Definition: libisofs.h:233
@ LIBISO_DIR
Definition: libisofs.h:229
@ LIBISO_FILE
Definition: libisofs.h:230
IsoStream * iso_stream_get_input_stream(IsoStream *stream, int flag)
Definition: stream.c:867
int iso_nowtime(time_t *now, int flag)
Definition: util.c:2494
int iso_stream_open(IsoStream *stream)
Definition: stream.c:798
#define ISO_FILE_NOT_OPENED
Definition: libisofs.h:8811
#define ISO_PATCH_OVERSIZED_BOOT
Definition: libisofs.h:9208
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream)
Definition: stream.c:751
#define ISO_NODE_DOESNT_EXIST
Definition: libisofs.h:8772
int iso_node_take(IsoNode *node)
Definition: node.c:810
off_t iso_stream_get_size(IsoStream *stream)
Definition: stream.c:810
IsoDir * iso_node_get_parent(IsoNode *node)
Definition: node.c:908
#define ISO_FILE_READ_ERROR
Definition: libisofs.h:8820
void iso_node_set_hidden(IsoNode *node, int hide_attrs)
Definition: node.c:558
#define ISO_WRONG_ARG_VALUE
Definition: libisofs.h:8751
int iso_stream_read(IsoStream *stream, void *buf, size_t count)
Definition: stream.c:816
void iso_node_ref(IsoNode *node)
Definition: node.c:46
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
@ LIBISO_HIDE_ON_HFSPLUS
Definition: libisofs.h:311
@ LIBISO_HIDE_ON_FAT
Definition: libisofs.h:316
#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
void iso_stream_unref(IsoStream *stream)
Definition: stream.c:789
#define ISO_BOOT_NO_CATALOG
Definition: libisofs.h:8786
int iso_stream_close(IsoStream *stream)
Definition: stream.c:804
#define ISO_BOOT_NO_EFI_ELTO
Definition: libisofs.h:9141
#define ISO_FILE_ALREADY_OPENED
Definition: libisofs.h:8796
#define ISO_NODE_NAME_NOT_UNIQUE
Definition: libisofs.h:8766
int iso_stream_is_repeatable(IsoStream *stream)
Definition: stream.c:822
#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
void iso_msg_debug(int imgid, const char *fmt,...)
Definition: messages.c:253
int iso_node_is_valid_name(const char *name)
Definition: node.c:1245
off_t size
Definition: eltorito.h:35
IsoNode node
Definition: eltorito.h:28
char * content
Definition: eltorito.h:36
uint32_t lba
Definition: eltorito.h:34
Definition: node.h:140
IsoNode * children
Definition: node.h:144
IsoNode node
Definition: node.h:141
size_t nchildren
Definition: node.h:143
IsoStream * stream
Definition: filesrc.h:60
struct iso_file_section * sections
Definition: filesrc.h:56
unsigned int checksum_index
Definition: filesrc.h:39
int sort_weight
Definition: filesrc.h:59
int nsections
Definition: filesrc.h:57
unsigned int no_write
Definition: filesrc.h:33
Definition: node.h:149
int sort_weight
Definition: node.h:165
unsigned int from_old_session
Definition: node.h:155
unsigned int explicit_weight
Definition: node.h:159
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
struct el_torito_boot_catalog * bootcat
Definition: image.h:62
int id
Definition: image.h:97
IsoDir * root
Definition: image.h:43
Definition: node.h:100
int refcount
Definition: node.h:108
gid_t gid
Definition: node.h:117
time_t ctime
Definition: node.h:122
uid_t uid
Definition: node.h:116
char * name
Definition: node.h:113
time_t atime
Definition: node.h:120
IsoDir * parent
Definition: node.h:126
enum IsoNodeType type
Definition: node.h:111
mode_t mode
Definition: node.h:115
int hidden
Definition: node.h:124
IsoNode * next
Definition: node.h:131
time_t mtime
Definition: node.h:121
uint8_t bi_reserved[(56) -(17)+1]
Definition: eltorito.c:37
uint8_t bi_length[(12) -(9)+1]
Definition: eltorito.c:35
uint8_t bi_file[(8) -(5)+1]
Definition: eltorito.c:34
uint8_t bi_csum[(16) -(13)+1]
Definition: eltorito.c:36
uint8_t bi_pvd[(4) -(1)+1]
Definition: eltorito.c:33
Ecma119Image * target
Definition: eltorito.c:860
uint8_t buffer[2048]
Definition: eltorito.c:861
uint8_t std_identifier[(6) -(2)+1]
Definition: ecma119.h:1000
uint8_t boot_sys_id[(39) -(8)+1]
Definition: ecma119.h:1002
uint8_t vol_desc_version[(7) -(7)+1]
Definition: ecma119.h:1001
uint8_t vol_desc_type[(1) -(1)+1]
Definition: ecma119.h:999
uint8_t boot_catalog[(75) -(72)+1]
Definition: ecma119.h:1004
IsoImage * image
Definition: ecma119.h:560
struct el_torito_boot_catalog * catalog
Definition: ecma119.h:685
uint32_t appended_part_size[8]
Definition: ecma119.h:825
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t * boot_intvl_start
Definition: ecma119.h:693
uint32_t * boot_intvl_size
Definition: ecma119.h:694
IsoImageWriter ** writers
Definition: ecma119.h:753
IsoFileSrc * efi_boot_part_filesrc
Definition: ecma119.h:888
uint32_t appended_part_start[8]
Definition: ecma119.h:824
size_t nwriters
Definition: ecma119.h:752
uint32_t curblock
Definition: ecma119.h:618
IsoFileSrc ** bootsrc
Definition: ecma119.h:689
int * boot_appended_idx
Definition: ecma119.h:691
off_t total_size
Definition: ecma119.h:599
IsoFileSrc * cat
Definition: ecma119.h:686
uint32_t eff_partition_offset
Definition: ecma119.h:794
struct el_torito_boot_image * bootimages[32]
Definition: eltorito.h:46
uint16_t load_size
Definition: eltorito.h:94
unsigned int isolinux_options
Definition: eltorito.h:83
uint32_t appended_size
Definition: eltorito.h:59
IsoFile * image
Definition: eltorito.h:54
unsigned char type
Definition: eltorito.h:85
unsigned int seems_isohybrid_capable
Definition: eltorito.h:70
uint8_t id_string[28]
Definition: eltorito.h:100
unsigned int bootable
Definition: eltorito.h:61
uint16_t load_seg
Definition: eltorito.h:93
unsigned int seems_grub2_boot_info
Definition: eltorito.h:66
unsigned int seems_boot_info_table
Definition: eltorito.h:65
uint32_t appended_start
Definition: eltorito.h:58
uint8_t selection_crit[20]
Definition: eltorito.h:101
unsigned char partition_type
Definition: eltorito.h:89
uint8_t platform_id
Definition: eltorito.h:99
Definition: eltorito.h:137
uint8_t load_seg[(4) -(3)+1]
Definition: eltorito.h:140
uint8_t vendor_sc[(32) -(14)+1]
Definition: eltorito.h:146
uint8_t boot_media_type[(2) -(2)+1]
Definition: eltorito.h:139
uint8_t boot_indicator[(1) -(1)+1]
Definition: eltorito.h:138
uint8_t sec_count[(8) -(7)+1]
Definition: eltorito.h:143
uint8_t block[(12) -(9)+1]
Definition: eltorito.h:144
uint8_t system_type[(5) -(5)+1]
Definition: eltorito.h:141
uint8_t selec_criteria[(13) -(13)+1]
Definition: eltorito.h:145
uint8_t num_entries[(4) -(3)+1]
Definition: eltorito.h:132
uint8_t id_string[(32) -(5)+1]
Definition: eltorito.h:133
uint8_t platform_id[(2) -(2)+1]
Definition: eltorito.h:131
uint8_t header_indicator[(1) -(1)+1]
Definition: eltorito.h:130
Definition: eltorito.h:106
uint8_t id_string[(28) -(5)+1]
Definition: eltorito.h:110
uint8_t key_byte2[(32) -(32)+1]
Definition: eltorito.h:113
uint8_t checksum[(30) -(29)+1]
Definition: eltorito.h:111
uint8_t platform_id[(2) -(2)+1]
Definition: eltorito.h:108
uint8_t header_id[(1) -(1)+1]
Definition: eltorito.h:107
uint8_t key_byte1[(31) -(31)+1]
Definition: eltorito.h:112
uint8_t opt_disk_sg[4]
Definition: eltorito.c:58
uint8_t code_area[440]
Definition: eltorito.c:57
struct partition_desc partition[4]
Definition: eltorito.c:60
uint8_t sign1
Definition: eltorito.c:61
uint8_t sign2
Definition: eltorito.c:62
uint8_t pad[2]
Definition: eltorito.c:59
uint32_t size
Definition: libisofs.h:259
uint32_t block
Definition: libisofs.h:258
int refcount
Definition: libisofs.h:1186
void * data
Definition: libisofs.h:1187
IsoStreamIface * class
Definition: libisofs.h:1185
char * efi_boot_partition
Definition: ecma119.h:476
uint32_t ms_block
Definition: ecma119.h:379
unsigned int appendable
Definition: ecma119.h:364
uint8_t boot_ind
Definition: eltorito.c:45
uint8_t size[4]
Definition: eltorito.c:50
uint8_t end_chs[3]
Definition: eltorito.c:48
uint8_t begin_chs[3]
Definition: eltorito.c:46
uint8_t type
Definition: eltorito.c:47
uint8_t start[4]
Definition: eltorito.c:49