patch: make *outfile extern
[platform/upstream/cdrkit.git] / genisoimage / boot-alpha.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /*
14  * Program boot-alpha.c - Handle Linux alpha boot extensions to iso9660.
15  *
16  * Written by Steve McIntyre <steve@einval.com> June 2004
17  *
18  * Heavily inspired by isomarkboot by David Mosberger in 1996.
19  *
20  * Copyright 2004 Steve McIntyre
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2, or (at your option)
25  * any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35  */
36
37 #include <mconfig.h>
38 #include "genisoimage.h"
39 #include <fctldefs.h>
40 #include <utypes.h>
41 #include <intcvt.h>
42 #include "match.h"
43 #include "diskmbr.h"
44 #include "bootinfo.h"
45 #include <schily.h>
46 #include "endianconv.h"
47
48         int     add_boot_alpha_filename(char *filename);
49 static  int     boot_alpha_write(FILE *outfile);
50 static  int     boot_alpha_hppa_write(FILE *outfile);
51 static  char   *boot_file_name = NULL;
52
53 unsigned long long alpha_hppa_boot_sector[256]; /* One (ISO) sector */
54 int boot_sector_initialized = 0;
55
56 #define BOOT_STRING "Linux/Alpha aboot for ISO filesystem."
57
58 /* Simple function: store the filename to be used later when we need
59    to find the boot file */
60 extern int add_boot_alpha_filename(char *filename)
61 {
62     boot_file_name = filename;
63     return 0;
64 }
65
66 static int boot_alpha_write(FILE *outfile)
67 {
68     struct directory_entry      *boot_file;     /* Boot file we need to search for */
69     unsigned long length = 0;
70     unsigned long extent = 0;
71
72     if (!boot_sector_initialized) {
73         memset(alpha_hppa_boot_sector, 0, sizeof(alpha_hppa_boot_sector));
74         boot_sector_initialized = 1;
75     }
76
77     /* Write the text header into the boot sector */
78     strcpy((char *)alpha_hppa_boot_sector, BOOT_STRING);
79
80     /* Find the dir entry for the boot file by walking our file list */
81     boot_file = search_tree_file(root, boot_file_name);
82     if (!boot_file) {
83 #ifdef  USE_LIBSCHILY
84                 comerrno(EX_BAD, "Uh oh, I cant find the Alpha boot file '%s'!\n",
85                                                         boot_file_name);
86 #else
87                 fprintf(stderr, "Uh oh, I cant find the Alpha boot file '%s'!\n",
88                                                         boot_file_name);
89                 exit(1);
90 #endif
91     }
92
93     /* Grab the ISO start sector and length from the dir entry. ISO
94        uses 2048-byte sectors, but we convert to 512-byte sectors here
95        for the sake of the firmware */
96     extent = get_733(boot_file->isorec.extent);
97     extent *= 4;
98     
99     length = get_733(boot_file->isorec.size);
100     length /= 512; /* I'm sure we should take account of any overlap
101                       here, but I'm copying what isomarkboot
102                       does. Maybe the boot files are specified to be
103                       exact multiples of 512 bytes? */
104
105     fprintf(stderr, "Found alpha boot image %s: using extent %lu, #blocks %lu\n",
106             boot_file_name, extent, length);
107
108     /* Now write those values into the appropriate area of the boot
109        sector in LITTLE ENDIAN format. */
110     write_le64(length, (unsigned char *)&alpha_hppa_boot_sector[60]);
111     write_le64(extent, (unsigned char *)&alpha_hppa_boot_sector[61]);
112
113     return 0;
114 }
115
116 static int boot_alpha_hppa_write(FILE *outfile)
117 {
118     unsigned long long sum = 0;
119     int i = 0;
120
121     /* Now generate a checksum of the first 504 bytes of the boot
122        sector and place it in alpha_hppa_boot_sector[63]. Isomarkboot currently
123        gets this wrong and will not work on big-endian systems! */
124     for (i = 0; i < 63; i++)
125         sum += read_le64((unsigned char *)&alpha_hppa_boot_sector[i]);
126
127     write_le64(sum, (unsigned char *)&alpha_hppa_boot_sector[63]);
128
129     jtwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, 0, FALSE);
130     xfwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, outfile, 0, FALSE);
131     last_extent_written++;
132
133     return 0;
134 }
135
136 struct output_fragment alphaboot_desc = {NULL, NULL, NULL, boot_alpha_write, "alpha boot block"};
137 struct output_fragment alpha_hppa_boot_desc = {NULL, oneblock_size, NULL, boot_alpha_hppa_write, "alpha/hppa boot block"};