Adding debian version 3.70~pre8+dfsg-1.
[syslinux-debian/hramrach.git] / gpxe / src / util / zbin.c
blobf47fa36ba5f18b3ee4f605f46d86762d86e40798
1 #include <stdio.h>
2 #include <sys/stat.h>
4 #define ENCODE
5 #define VERBOSE
6 #include "nrv2b.c"
7 FILE *infile, *outfile;
9 struct input_file {
10 void *buf;
11 size_t len;
14 struct output_file {
15 void *buf;
16 size_t len;
17 size_t max_len;
20 struct zinfo_common {
21 char type[4];
22 char pad[12];
25 struct zinfo_copy {
26 char type[4];
27 uint32_t offset;
28 uint32_t len;
29 uint32_t align;
32 struct zinfo_pack {
33 char type[4];
34 uint32_t offset;
35 uint32_t len;
36 uint32_t align;
39 struct zinfo_subtract {
40 char type[4];
41 uint32_t offset;
42 uint32_t divisor;
43 uint32_t pad;
46 union zinfo_record {
47 struct zinfo_common common;
48 struct zinfo_copy copy;
49 struct zinfo_pack pack;
50 struct zinfo_subtract subtract;
53 struct zinfo_file {
54 union zinfo_record *zinfo;
55 unsigned int num_entries;
58 static int read_file ( const char *filename, void **buf, size_t *len ) {
59 FILE *file;
60 struct stat stat;
62 file = fopen ( filename, "r" );
63 if ( ! file ) {
64 fprintf ( stderr, "Could not open %s: %s\n", filename,
65 strerror ( errno ) );
66 goto err;
69 if ( fstat ( fileno ( file ), &stat ) < 0 ) {
70 fprintf ( stderr, "Could not stat %s: %s\n", filename,
71 strerror ( errno ) );
72 goto err;
75 *len = stat.st_size;
76 *buf = malloc ( *len );
77 if ( ! *buf ) {
78 fprintf ( stderr, "Could not malloc() %d bytes for %s: %s\n",
79 *len, filename, strerror ( errno ) );
80 goto err;
83 if ( fread ( *buf, 1, *len, file ) != *len ) {
84 fprintf ( stderr, "Could not read %d bytes from %s: %s\n",
85 *len, filename, strerror ( errno ) );
86 goto err;
89 fclose ( file );
90 return 0;
92 err:
93 fclose ( file );
94 return -1;
97 static int read_input_file ( const char *filename,
98 struct input_file *input ) {
99 return read_file ( filename, &input->buf, &input->len );
102 static int read_zinfo_file ( const char *filename,
103 struct zinfo_file *zinfo ) {
104 void *buf;
105 size_t len;
107 if ( read_file ( filename, &buf, &len ) < 0 )
108 return -1;
110 if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
111 fprintf ( stderr, ".zinfo file %s has invalid length %d\n",
112 filename, len );
113 return -1;
116 zinfo->zinfo = buf;
117 zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
118 return 0;
121 static int alloc_output_file ( size_t max_len, struct output_file *output ) {
122 output->len = 0;
123 output->max_len = ( max_len );
124 output->buf = malloc ( max_len );
125 if ( ! output->buf ) {
126 fprintf ( stderr, "Could not allocate %d bytes for output\n",
127 max_len );
128 return -1;
130 memset ( output->buf, 0xff, sizeof ( output->buf ) );
131 return 0;
134 static int process_zinfo_copy ( struct input_file *input,
135 struct output_file *output,
136 union zinfo_record *zinfo ) {
137 struct zinfo_copy *copy = &zinfo->copy;
138 size_t offset = copy->offset;
139 size_t len = copy->len;
140 unsigned int align = copy->align;
142 if ( ( offset + len ) > input->len ) {
143 fprintf ( stderr, "Input buffer overrun on copy\n" );
144 return -1;
147 output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
148 if ( ( output->len + len ) > output->max_len ) {
149 fprintf ( stderr, "Output buffer overrun on copy\n" );
150 return -1;
153 memcpy ( ( output->buf + output->len ),
154 ( input->buf + offset ), len );
155 output->len += len;
156 return 0;
159 static int process_zinfo_pack ( struct input_file *input,
160 struct output_file *output,
161 union zinfo_record *zinfo ) {
162 struct zinfo_pack *pack = &zinfo->pack;
163 size_t offset = pack->offset;
164 size_t len = pack->len;
165 unsigned int align = pack->align;
166 unsigned long packed_len;
168 if ( ( offset + len ) > input->len ) {
169 fprintf ( stderr, "Input buffer overrun on pack\n" );
170 return -1;
173 output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
174 if ( output->len > output->max_len ) {
175 fprintf ( stderr, "Output buffer overrun on pack\n" );
176 return -1;
179 if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
180 ( output->buf + output->len ),
181 &packed_len, 0 ) != UCL_E_OK ) {
182 fprintf ( stderr, "Compression failure\n" );
183 return -1;
186 output->len += packed_len;
187 if ( output->len > output->max_len ) {
188 fprintf ( stderr, "Output buffer overrun on pack\n" );
189 return -1;
192 return 0;
195 static int process_zinfo_subtract ( struct input_file *input,
196 struct output_file *output,
197 struct zinfo_subtract *subtract,
198 size_t datasize ) {
199 size_t offset = subtract->offset;
200 void *target;
201 long delta;
203 if ( ( offset + datasize ) > output->len ) {
204 fprintf ( stderr, "Subtract at %#zx outside output buffer\n",
205 offset );
206 return -1;
209 target = ( output->buf + offset );
210 delta = ( ( output->len / subtract->divisor ) -
211 ( input->len / subtract->divisor ) );
213 switch ( datasize ) {
214 case 1: {
215 uint8_t *byte = target;
216 *byte += delta;
217 break; }
218 case 2: {
219 uint16_t *word = target;
220 *word += delta;
221 break; }
222 case 4: {
223 uint32_t *dword = target;
224 *dword += delta;
225 break; }
226 default:
227 fprintf ( stderr, "Unsupported subtract datasize %d\n",
228 datasize );
229 return -1;
231 return 0;
234 static int process_zinfo_subb ( struct input_file *input,
235 struct output_file *output,
236 union zinfo_record *zinfo ) {
237 return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 );
240 static int process_zinfo_subw ( struct input_file *input,
241 struct output_file *output,
242 union zinfo_record *zinfo ) {
243 return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 );
246 static int process_zinfo_subl ( struct input_file *input,
247 struct output_file *output,
248 union zinfo_record *zinfo ) {
249 return process_zinfo_subtract ( input, output, &zinfo->subtract, 4 );
252 struct zinfo_processor {
253 char *type;
254 int ( * process ) ( struct input_file *input,
255 struct output_file *output,
256 union zinfo_record *zinfo );
259 static struct zinfo_processor zinfo_processors[] = {
260 { "COPY", process_zinfo_copy },
261 { "PACK", process_zinfo_pack },
262 { "SUBB", process_zinfo_subb },
263 { "SUBW", process_zinfo_subw },
264 { "SUBL", process_zinfo_subl },
267 static int process_zinfo ( struct input_file *input,
268 struct output_file *output,
269 union zinfo_record *zinfo ) {
270 struct zinfo_common *common = &zinfo->common;
271 struct zinfo_processor *processor;
272 char type[ sizeof ( common->type ) + 1 ] = "";
273 unsigned int i;
275 strncat ( type, common->type, sizeof ( type ) - 1 );
276 for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
277 sizeof ( zinfo_processors[0] ) ) ; i++ ) {
278 processor = &zinfo_processors[i];
279 if ( strcmp ( processor->type, type ) == 0 )
280 return processor->process ( input, output, zinfo );
283 fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
284 return -1;
287 static int write_output_file ( struct output_file *output ) {
288 if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
289 fprintf ( stderr, "Could not write %d bytes of output: %s\n",
290 output->len, strerror ( errno ) );
291 return -1;
293 return 0;
296 int main ( int argc, char **argv ) {
297 struct input_file input;
298 struct output_file output;
299 struct zinfo_file zinfo;
300 unsigned int i;
302 if ( argc != 3 ) {
303 fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
304 "> file.zbin\n", argv[0] );
305 exit ( 1 );
308 if ( read_input_file ( argv[1], &input ) < 0 )
309 exit ( 1 );
310 if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
311 exit ( 1 );
312 if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
313 exit ( 1 );
315 for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
316 if ( process_zinfo ( &input, &output,
317 &zinfo.zinfo[i] ) < 0 )
318 exit ( 1 );
321 if ( write_output_file ( &output ) < 0 )
322 exit ( 1 );
324 return 0;