1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * rdf2bin.c - convert an RDOFF object file to flat binary
50 static uint32_t origin
= 0;
51 static bool origin_def
= false;
52 static uint32_t align
= 16;
53 static bool align_def
= false;
55 struct output_format
{
59 int (*output
)(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
);
63 static int null_init_fini(FILE *f
)
69 static int com_init(FILE *f
)
77 static int output_bin(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
79 static uint32_t offset
= 0; /* Current file offset, if applicable */
82 if (where
-origin
< offset
) {
83 fprintf(stderr
, "%s: internal error: backwards movement\n", progname
);
87 pad
= (where
-origin
) - offset
;
91 if (fwrite(data
, 1, bytes
, f
) != bytes
)
98 static int write_ith_record(FILE *f
, unsigned int len
, uint16_t addr
,
99 uint8_t type
, void *data
)
101 char buf
[1+2+4+2+255*2+2+2];
103 uint8_t csum
, *dptr
= data
;
107 fprintf(stderr
, "%s: internal error: invalid ith record size\n",
112 csum
= len
+ addr
+ (addr
>> 8) + type
;
113 for (i
= 0; i
< len
; i
++)
117 p
+= sprintf(p
, ":%02X%04X%02X", len
, addr
, type
);
118 for (i
= 0; i
< len
; i
++)
119 p
+= sprintf(p
, "%02X", dptr
[i
]);
120 p
+= sprintf(p
, "%02X\n", csum
);
122 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
128 static int output_ith(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
130 static uint32_t last
= 0; /* Last address written */
132 uint8_t *dbuf
= data
;
136 if ((where
^ last
) & ~0xffff) {
137 abuf
[0] = where
>> 24;
138 abuf
[1] = where
>> 16;
139 if (write_ith_record(f
, 2, 0, 4, abuf
))
143 /* Output up to 32 bytes, but always end on an aligned boundary */
144 chunk
= 32 - (where
& 31);
148 if (write_ith_record(f
, chunk
, (uint16_t)where
, 0, dbuf
))
152 last
= where
+ chunk
- 1;
159 static int fini_ith(FILE *f
)
161 /* XXX: entry point? */
162 return write_ith_record(f
, 0, 0, 1, NULL
);
165 static int write_srecord(FILE *f
, unsigned int len
, unsigned int alen
,
166 uint32_t addr
, uint8_t type
, void *data
)
168 char buf
[2+2+8+255*2+2+2];
170 uint8_t csum
, *dptr
= data
;
174 fprintf(stderr
, "%s: internal error: invalid srec record size\n",
189 fprintf(stderr
, "%s: internal error: invalid srec address length\n",
194 csum
= (len
+alen
+1) + addr
+ (addr
>> 8) + (addr
>> 16) + (addr
>> 24);
195 for (i
= 0; i
< len
; i
++)
199 p
+= sprintf(p
, "S%c%02X%0*X", type
, len
+alen
+1, alen
*2, addr
);
200 for (i
= 0; i
< len
; i
++)
201 p
+= sprintf(p
, "%02X", dptr
[i
]);
202 p
+= sprintf(p
, "%02X\n", csum
);
204 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
210 static int init_srec(FILE *f
)
212 return write_srecord(f
, 0, 2, 0, '0', NULL
);
215 static int fini_srec(FILE *f
)
217 /* XXX: entry point? */
218 return write_srecord(f
, 0, 4, 0, '7', NULL
);
221 static int output_srec(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
223 uint8_t *dbuf
= data
;
227 /* Output up to 32 bytes, but always end on an aligned boundary */
228 chunk
= 32 - (where
& 31);
232 if (write_srecord(f
, chunk
, 4, where
, '3', dbuf
))
242 static struct output_format output_formats
[] = {
243 { "bin", "wb", null_init_fini
, output_bin
, null_init_fini
},
244 { "com", "wb", com_init
, output_bin
, null_init_fini
},
245 { "ith", "wt", null_init_fini
, output_ith
, fini_ith
},
246 { "ihx", "wt", null_init_fini
, output_ith
, fini_ith
},
247 { "srec", "wt", init_srec
, output_srec
, fini_srec
},
248 { NULL
, NULL
, NULL
, NULL
, NULL
}
251 static const char *getformat(const char *pathname
)
254 static char fmt_buf
[16];
257 * Search backwards for the string "rdf2" followed by a string
258 * of alphanumeric characters. This should handle path prefixes,
259 * as well as extensions (e.g. C:\FOO\RDF2SREC.EXE).
261 for (p
= strchr(pathname
, '\0')-1 ; p
>= pathname
; p
--) {
262 if (!nasm_stricmp(p
, "rdf2")) {
265 while (isalnum(*q
) && r
< fmt_buf
+sizeof fmt_buf
-1)
275 static void usage(void)
278 "Usage: %s [options] input-file output-file\n"
280 " -o origin Specify the relocation origin\n"
281 " -p alignment Specify minimum segment alignment\n"
282 " -f format Select format (bin, com, ith, srec)\n"
288 int main(int argc
, char **argv
)
293 int codepad
, datapad
;
294 const char *format
= NULL
;
295 const struct output_format
*fmt
;
310 if (argv
[0][0] == '-' && argv
[0][1] && !argv
[0][2]) {
311 switch (argv
[0][1]) {
314 origin
= readnum(*argv
, &err
);
316 fprintf(stderr
, "%s: invalid parameter: %s\n",
324 align
= readnum(*argv
, &err
);
326 fprintf(stderr
, "%s: invalid parameter: %s\n",
346 fprintf(stderr
, "%s: unknown option: %s\n",
360 format
= getformat(progname
);
363 fprintf(stderr
, "%s: unable to determine desired output format\n",
368 for (fmt
= output_formats
; fmt
->name
; fmt
++) {
369 if (!nasm_stricmp(format
, fmt
->name
))
374 fprintf(stderr
, "%s: unknown output format: %s\n", progname
, format
);
381 rdfperror(progname
, *argv
);
386 printf("relocating %s: origin=%"PRIx32
", align=%d\n",
387 *argv
, origin
, align
);
390 m
->datarel
= origin
+ m
->f
.seg
[0].length
;
391 if (m
->datarel
% align
!= 0) {
392 codepad
= align
- (m
->datarel
% align
);
393 m
->datarel
+= codepad
;
397 m
->bssrel
= m
->datarel
+ m
->f
.seg
[1].length
;
398 if (m
->bssrel
% align
!= 0) {
399 datapad
= align
- (m
->bssrel
% align
);
400 m
->bssrel
+= datapad
;
405 printf("code: %08"PRIx32
"\ndata: %08"PRIx32
"\nbss: %08"PRIx32
"\n",
406 m
->textrel
, m
->datarel
, m
->bssrel
);
412 of
= fopen(*argv
, fmt
->mode
);
414 fprintf(stderr
, "%s: could not open output file %s: %s\n",
415 progname
, *argv
, strerror(errno
));
420 fmt
->output(of
, m
->t
, m
->f
.seg
[0].length
, m
->textrel
) ||
421 fmt
->output(of
, m
->d
, m
->f
.seg
[1].length
, m
->datarel
) ||
423 fprintf(stderr
, "%s: error writing to %s: %s\n",
424 progname
, *argv
, strerror(errno
));