2
* Program eltorito.c - Handle El Torito specific extensions to iso9660.
5
Written by Michael Fulbright <msf@redhat.com> (1996).
7
Copyright 1996 RedHat Software, Incorporated
9
Copyright (C) 2009 Free Software Foundation, Inc.
11
Boot Info Table generation based on code from genisoimage.c
12
(from cdrkit 1.1.9), which was originally licensed under GPLv2+.
14
This program is free software; you can redistribute it and/or modify
15
it under the terms of the GNU General Public License as published by
16
the Free Software Foundation; either version 3, or (at your option)
19
This program is distributed in the hope that it will be useful,
20
but WITHOUT ANY WARRANTY; without even the implied warranty of
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
GNU General Public License for more details.
24
You should have received a copy of the GNU General Public License
25
along with this program; if not, see <http://www.gnu.org/licenses/>.
30
#include <sys/types.h>
41
/* used by Win32 for opening binary file - not used by Unix */
47
#define MIN(a, b) (((a) < (b))? (a): (b))
49
static struct eltorito_validation_entry valid_desc;
50
static struct eltorito_defaultboot_entry default_desc;
51
static struct eltorito_boot_descriptor gboot_desc;
53
static int tvd_write __PR((FILE * outfile));
56
* Check for presence of boot catalog. If it does not exist then make it
58
void FDECL1(init_boot_catalog, const char *, path)
61
char * bootpath; /* filename of boot catalog */
65
bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
66
strcpy(bootpath, path);
67
if (bootpath[strlen(bootpath)-1] != '/')
72
strcat(bootpath, boot_catalog);
75
* check for the file existing
78
fprintf(stderr,"Looking for boot catalog file %s\n",bootpath);
81
if (!stat_filter(bootpath, &statbuf))
84
* make sure its big enough to hold what we want
86
if (statbuf.st_size == 2048)
89
* printf("Boot catalog exists, so we do nothing\n");
96
fprintf (stderr, _("A boot catalog exists and appears corrupted.\n"));
97
fprintf (stderr, _("Please check the following file: %s.\n"), bootpath);
98
fprintf (stderr, _("This file must be removed before a bootable CD can be done.\n"));
105
* file does not exist, so we create it
106
* make it one CD sector long
108
bcat = fopen (bootpath, "wb");
110
error (1, errno, _("Error creating boot catalog (%s)"), bootpath);
112
buf = (char *) e_malloc( 2048 );
113
if (fwrite (buf, 1, 2048, bcat) != 2048)
114
error (1, errno, _("Error writing to boot catalog (%s)"), bootpath);
116
chmod (bootpath, S_IROTH | S_IRGRP | S_IRWXU);
119
} /* init_boot_catalog(... */
121
void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
125
unsigned char * checksum_ptr;
126
struct directory_entry * de;
127
struct directory_entry * de2;
131
memset(boot_desc, 0, sizeof(*boot_desc));
132
boot_desc->id[0] = 0;
133
memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
134
boot_desc->version[0] = 1;
136
memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
139
* search from root of iso fs to find boot catalog
141
de2 = search_tree_file(root, boot_catalog);
144
fprintf (stderr, _("Boot catalog cannot be found!\n"));
148
set_731(boot_desc->bootcat_ptr,
149
(unsigned int) get_733(de2->isorec.extent));
152
* now adjust boot catalog
153
* lets find boot image first
155
de=search_tree_file(root, boot_image);
158
fprintf (stderr, _("Boot image cannot be found!\n"));
163
* we have the boot image, so write boot catalog information
164
* Next we write out the primary descriptor for the disc
166
memset(&valid_desc, 0, sizeof(valid_desc));
167
valid_desc.headerid[0] = 1;
168
valid_desc.arch[0] = EL_TORITO_ARCH_x86;
171
* we'll shove start of publisher id into id field, may get truncated
172
* but who really reads this stuff!
175
memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher)));
177
valid_desc.key1[0] = 0x55;
178
valid_desc.key2[0] = 0xAA;
181
* compute the checksum
184
checksum_ptr = (unsigned char *) &valid_desc;
185
for (i=0; i<sizeof(valid_desc); i+=2)
188
* skip adding in ckecksum word, since we dont have it yet!
194
checksum += (unsigned int)checksum_ptr[i];
195
checksum += ((unsigned int)checksum_ptr[i+1])*256;
199
* now find out the real checksum
201
checksum = -checksum;
202
set_721(valid_desc.cksum, (unsigned int) checksum);
205
* now make the initial/default entry for boot catalog
207
memset(&default_desc, 0, sizeof(default_desc));
208
default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
211
* use default BIOS loadpnt
213
set_721(default_desc.loadseg, 0);
214
default_desc.arch[0] = EL_TORITO_ARCH_x86;
217
* figure out size of boot image in sectors, for now hard code to
218
* assume 512 bytes/sector on a bootable floppy
220
nsectors = ((de->size + 511) & ~(511))/512;
221
fprintf (stderr, _("\nSize of boot image is %d sectors"), nsectors);
222
fprintf (stderr, " -> ");
224
if (! use_eltorito_emul_floppy)
226
default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
227
fprintf (stderr, _("No emulation\n"));
229
else if (nsectors == 2880 )
231
* choose size of emulated floppy based on boot image size
234
default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
235
fprintf (stderr, _("Emulating a 1.44 meg floppy\n"));
237
else if (nsectors == 5760 )
239
default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
240
fprintf (stderr, _("Emulating a 2.88 meg floppy\n"));
242
else if (nsectors == 2400 )
244
default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
245
fprintf (stderr, _("Emulating a 1.2 meg floppy\n"));
249
fprintf (stderr, _("\nError - boot image is not the an allowable size.\n"));
254
* FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!!
257
set_721(default_desc.nsect, (unsigned int) nsectors );
259
fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent));
261
set_731(default_desc.bootoff,
262
(unsigned int) get_733(de->isorec.extent));
265
* now write it to disk
267
bootcat = fopen (de2->whole_name, "r+b");
269
error (1, errno, _("Error opening boot catalog for update"));
274
if (fwrite (&valid_desc, 1, 32, bootcat) != 32)
275
error (1, errno, _("Error writing to boot catalog"));
276
if (fwrite (&default_desc, 1, 32, bootcat) != 32)
277
error (1, errno, _("Error writing to boot catalog"));
280
/* If the user has asked for it, patch the boot image */
281
if (use_boot_info_table)
284
uint32_t bi_checksum;
285
unsigned int total_len;
286
static char csum_buffer[SECTOR_SIZE];
288
struct eltorito_boot_info bi_table;
289
bootimage = fopen (de->whole_name, "r+b");
290
if (bootimage == NULL)
291
error (1, errno, _("Error opening boot image file `%s' for update"),
293
/* Compute checksum of boot image, sans 64 bytes */
296
while ((len = fread (csum_buffer, 1, SECTOR_SIZE, bootimage)) > 0)
299
error (1, 0, _("Odd alignment at non-end-of-file in boot image `%s'"),
302
memset (csum_buffer, 0, 64 - total_len);
303
if (len < SECTOR_SIZE)
304
memset (csum_buffer + len, 0, SECTOR_SIZE - len);
305
for (i = 0; i < SECTOR_SIZE; i += 4)
306
bi_checksum += get_731 (&csum_buffer[i]);
310
if (total_len != de->size)
311
error (1, 0, _("Boot image file `%s' changed unexpectedly"),
313
/* End of file, set position to byte 8 */
314
fseeko (bootimage, (off_t) 8, SEEK_SET);
315
memset (&bi_table, 0, sizeof (bi_table));
316
/* Is it always safe to assume PVD is at session_start+16? */
317
set_731 (bi_table.pvd_addr, session_start + 16);
318
set_731 (bi_table.file_addr, de->starting_block);
319
set_731 (bi_table.file_length, de->size);
320
set_731 (bi_table.file_checksum, bi_checksum);
322
if (fwrite (&bi_table, 1, sizeof (bi_table), bootimage) != sizeof (bi_table))
323
error (1, errno, _("Error writing to boot image (%s)"), bootimage);
327
} /* get_torito_desc(... */
330
* Function to write the EVD for the disc.
332
static int FDECL1(tvd_write, FILE *, outfile)
335
* Next we write out the boot volume descriptor for the disc
337
get_torito_desc(&gboot_desc);
338
xfwrite(&gboot_desc, 1, 2048, outfile);
339
last_extent_written ++;
343
struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};