eltorito.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Program eltorito.c - Handle El Torito specific extensions to iso9660.
  3. *
  4. Written by Michael Fulbright <msf@redhat.com> (1996).
  5. Copyright 1996 RedHat Software, Incorporated
  6. Copyright (C) 2009 Free Software Foundation, Inc.
  7. Boot Info Table generation based on code from genisoimage.c
  8. (from cdrkit 1.1.9), which was originally licensed under GPLv2+.
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 3, or (at your option)
  12. any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <unistd.h>
  24. #include <fcntl.h>
  25. #include <stdlib.h>
  26. #include <errno.h>
  27. #include "config.h"
  28. #include "mkisofs.h"
  29. #include "iso9660.h"
  30. /* used by Win32 for opening binary file - not used by Unix */
  31. #ifndef O_BINARY
  32. #define O_BINARY 0
  33. #endif /* O_BINARY */
  34. #undef MIN
  35. #define MIN(a, b) (((a) < (b))? (a): (b))
  36. static struct eltorito_validation_entry valid_desc;
  37. static struct eltorito_defaultboot_entry default_desc;
  38. static struct eltorito_boot_descriptor gboot_desc;
  39. static int tvd_write __PR((FILE * outfile));
  40. /*
  41. * Check for presence of boot catalog. If it does not exist then make it
  42. */
  43. void FDECL1(init_boot_catalog, const char *, path)
  44. {
  45. FILE *bcat;
  46. char * bootpath; /* filename of boot catalog */
  47. char * buf;
  48. struct stat statbuf;
  49. bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
  50. strcpy(bootpath, path);
  51. if (bootpath[strlen(bootpath)-1] != '/')
  52. {
  53. strcat(bootpath,"/");
  54. }
  55. strcat(bootpath, boot_catalog);
  56. /*
  57. * check for the file existing
  58. */
  59. #ifdef DEBUG_TORITO
  60. fprintf(stderr,"Looking for boot catalog file %s\n",bootpath);
  61. #endif
  62. if (!stat_filter(bootpath, &statbuf))
  63. {
  64. /*
  65. * make sure its big enough to hold what we want
  66. */
  67. if (statbuf.st_size == 2048)
  68. {
  69. /*
  70. * printf("Boot catalog exists, so we do nothing\n");
  71. */
  72. free(bootpath);
  73. return;
  74. }
  75. else
  76. {
  77. fprintf (stderr, _("A boot catalog exists and appears corrupted.\n"));
  78. fprintf (stderr, _("Please check the following file: %s.\n"), bootpath);
  79. fprintf (stderr, _("This file must be removed before a bootable CD can be done.\n"));
  80. free (bootpath);
  81. exit (1);
  82. }
  83. }
  84. /*
  85. * file does not exist, so we create it
  86. * make it one CD sector long
  87. */
  88. bcat = fopen (bootpath, "wb");
  89. if (bcat == NULL)
  90. error (1, errno, _("Error creating boot catalog (%s)"), bootpath);
  91. buf = (char *) e_malloc( 2048 );
  92. if (fwrite (buf, 1, 2048, bcat) != 2048)
  93. error (1, errno, _("Error writing to boot catalog (%s)"), bootpath);
  94. fclose (bcat);
  95. chmod (bootpath, S_IROTH | S_IRGRP | S_IRWXU);
  96. free(bootpath);
  97. } /* init_boot_catalog(... */
  98. void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
  99. {
  100. FILE *bootcat;
  101. int checksum;
  102. unsigned char * checksum_ptr;
  103. struct directory_entry * de;
  104. struct directory_entry * de2;
  105. unsigned int i;
  106. int nsectors;
  107. memset(boot_desc, 0, sizeof(*boot_desc));
  108. boot_desc->id[0] = 0;
  109. memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
  110. boot_desc->version[0] = 1;
  111. memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
  112. /*
  113. * search from root of iso fs to find boot catalog
  114. */
  115. de2 = search_tree_file(root, boot_catalog);
  116. if (!de2)
  117. {
  118. fprintf (stderr, _("Boot catalog cannot be found!\n"));
  119. exit (1);
  120. }
  121. set_731(boot_desc->bootcat_ptr,
  122. (unsigned int) get_733(de2->isorec.extent));
  123. /*
  124. * now adjust boot catalog
  125. * lets find boot image first
  126. */
  127. de=search_tree_file(root, boot_image);
  128. if (!de)
  129. {
  130. fprintf (stderr, _("Boot image cannot be found!\n"));
  131. exit (1);
  132. }
  133. /*
  134. * we have the boot image, so write boot catalog information
  135. * Next we write out the primary descriptor for the disc
  136. */
  137. memset(&valid_desc, 0, sizeof(valid_desc));
  138. valid_desc.headerid[0] = 1;
  139. valid_desc.arch[0] = EL_TORITO_ARCH_x86;
  140. /*
  141. * we'll shove start of publisher id into id field, may get truncated
  142. * but who really reads this stuff!
  143. */
  144. if (publisher)
  145. memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher)));
  146. valid_desc.key1[0] = 0x55;
  147. valid_desc.key2[0] = 0xAA;
  148. /*
  149. * compute the checksum
  150. */
  151. checksum=0;
  152. checksum_ptr = (unsigned char *) &valid_desc;
  153. for (i=0; i<sizeof(valid_desc); i+=2)
  154. {
  155. /*
  156. * skip adding in ckecksum word, since we dont have it yet!
  157. */
  158. if (i == 28)
  159. {
  160. continue;
  161. }
  162. checksum += (unsigned int)checksum_ptr[i];
  163. checksum += ((unsigned int)checksum_ptr[i+1])*256;
  164. }
  165. /*
  166. * now find out the real checksum
  167. */
  168. checksum = -checksum;
  169. set_721(valid_desc.cksum, (unsigned int) checksum);
  170. /*
  171. * now make the initial/default entry for boot catalog
  172. */
  173. memset(&default_desc, 0, sizeof(default_desc));
  174. default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
  175. /*
  176. * use default BIOS loadpnt
  177. */
  178. set_721(default_desc.loadseg, 0);
  179. default_desc.arch[0] = EL_TORITO_ARCH_x86;
  180. /*
  181. * figure out size of boot image in sectors, for now hard code to
  182. * assume 512 bytes/sector on a bootable floppy
  183. */
  184. nsectors = ((de->size + 511) & ~(511))/512;
  185. fprintf (stderr, _("\nSize of boot image is %d sectors"), nsectors);
  186. fprintf (stderr, " -> ");
  187. if (! use_eltorito_emul_floppy)
  188. {
  189. default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
  190. fprintf (stderr, _("No emulation\n"));
  191. }
  192. else if (nsectors == 2880 )
  193. /*
  194. * choose size of emulated floppy based on boot image size
  195. */
  196. {
  197. default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
  198. fprintf (stderr, _("Emulating a 1.44 meg floppy\n"));
  199. }
  200. else if (nsectors == 5760 )
  201. {
  202. default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
  203. fprintf (stderr, _("Emulating a 2.88 meg floppy\n"));
  204. }
  205. else if (nsectors == 2400 )
  206. {
  207. default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
  208. fprintf (stderr, _("Emulating a 1.2 meg floppy\n"));
  209. }
  210. else
  211. {
  212. fprintf (stderr, _("\nError - boot image is not the an allowable size.\n"));
  213. exit (1);
  214. }
  215. /*
  216. * FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!!
  217. */
  218. nsectors = 1;
  219. set_721(default_desc.nsect, (unsigned int) nsectors );
  220. #ifdef DEBUG_TORITO
  221. fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent));
  222. #endif
  223. set_731(default_desc.bootoff,
  224. (unsigned int) get_733(de->isorec.extent));
  225. /*
  226. * now write it to disk
  227. */
  228. bootcat = fopen (de2->whole_name, "r+b");
  229. if (bootcat == NULL)
  230. error (1, errno, _("Error opening boot catalog for update"));
  231. /*
  232. * write out
  233. */
  234. if (fwrite (&valid_desc, 1, 32, bootcat) != 32)
  235. error (1, errno, _("Error writing to boot catalog"));
  236. if (fwrite (&default_desc, 1, 32, bootcat) != 32)
  237. error (1, errno, _("Error writing to boot catalog"));
  238. fclose (bootcat);
  239. /* If the user has asked for it, patch the boot image */
  240. if (use_boot_info_table)
  241. {
  242. FILE *bootimage;
  243. uint32_t bi_checksum;
  244. unsigned int total_len;
  245. static char csum_buffer[SECTOR_SIZE];
  246. int len;
  247. struct eltorito_boot_info bi_table;
  248. bootimage = fopen (de->whole_name, "r+b");
  249. if (bootimage == NULL)
  250. error (1, errno, _("Error opening boot image file `%s' for update"),
  251. de->whole_name);
  252. /* Compute checksum of boot image, sans 64 bytes */
  253. total_len = 0;
  254. bi_checksum = 0;
  255. while ((len = fread (csum_buffer, 1, SECTOR_SIZE, bootimage)) > 0)
  256. {
  257. if (total_len & 3)
  258. error (1, 0, _("Odd alignment at non-end-of-file in boot image `%s'"),
  259. de->whole_name);
  260. if (total_len < 64)
  261. memset (csum_buffer, 0, 64 - total_len);
  262. if (len < SECTOR_SIZE)
  263. memset (csum_buffer + len, 0, SECTOR_SIZE - len);
  264. for (i = 0; i < SECTOR_SIZE; i += 4)
  265. bi_checksum += get_731 (&csum_buffer[i]);
  266. total_len += len;
  267. }
  268. if (total_len != de->size)
  269. error (1, 0, _("Boot image file `%s' changed unexpectedly"),
  270. de->whole_name);
  271. /* End of file, set position to byte 8 */
  272. fseeko (bootimage, (off_t) 8, SEEK_SET);
  273. memset (&bi_table, 0, sizeof (bi_table));
  274. /* Is it always safe to assume PVD is at session_start+16? */
  275. set_731 (bi_table.pvd_addr, session_start + 16);
  276. set_731 (bi_table.file_addr, de->starting_block);
  277. set_731 (bi_table.file_length, de->size);
  278. set_731 (bi_table.file_checksum, bi_checksum);
  279. if (fwrite (&bi_table, 1, sizeof (bi_table), bootimage) != sizeof (bi_table))
  280. error (1, errno, _("Error writing to boot image (%s)"), bootimage);
  281. fclose (bootimage);
  282. }
  283. } /* get_torito_desc(... */
  284. /*
  285. * Function to write the EVD for the disc.
  286. */
  287. static int FDECL1(tvd_write, FILE *, outfile)
  288. {
  289. /*
  290. * Next we write out the boot volume descriptor for the disc
  291. */
  292. get_torito_desc(&gboot_desc);
  293. xfwrite(&gboot_desc, 1, 2048, outfile);
  294. last_extent_written ++;
  295. return 0;
  296. }
  297. struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};