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
51 static uint32_t origin
= 0;
52 static bool origin_def
= false;
53 static uint32_t align
= 16;
54 static bool align_def
= false;
56 struct output_format
{
60 int (*output
)(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
);
64 static int null_init_fini(FILE *f
)
70 static int com_init(FILE *f
)
78 static int output_bin(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
80 static uint32_t offset
= 0; /* Current file offset, if applicable */
83 if (where
-origin
< offset
) {
84 fprintf(stderr
, "%s: internal error: backwards movement\n", progname
);
88 pad
= (where
-origin
) - offset
;
89 if (fwritezero(pad
, f
) != pad
)
93 if (fwrite(data
, 1, bytes
, f
) != bytes
)
100 static int write_ith_record(FILE *f
, unsigned int len
, uint16_t addr
,
101 uint8_t type
, void *data
)
103 char buf
[1+2+4+2+255*2+2+2];
105 uint8_t csum
, *dptr
= data
;
109 fprintf(stderr
, "%s: internal error: invalid ith record size\n",
114 csum
= len
+ addr
+ (addr
>> 8) + type
;
115 for (i
= 0; i
< len
; i
++)
119 p
+= sprintf(p
, ":%02X%04X%02X", len
, addr
, type
);
120 for (i
= 0; i
< len
; i
++)
121 p
+= sprintf(p
, "%02X", dptr
[i
]);
122 p
+= sprintf(p
, "%02X\n", csum
);
124 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
130 static int output_ith(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
132 static uint32_t last
= 0; /* Last address written */
134 uint8_t *dbuf
= data
;
138 if ((where
^ last
) & ~0xffff) {
139 abuf
[0] = where
>> 24;
140 abuf
[1] = where
>> 16;
141 if (write_ith_record(f
, 2, 0, 4, abuf
))
145 /* Output up to 32 bytes, but always end on an aligned boundary */
146 chunk
= 32 - (where
& 31);
150 if (write_ith_record(f
, chunk
, (uint16_t)where
, 0, dbuf
))
154 last
= where
+ chunk
- 1;
161 static int fini_ith(FILE *f
)
163 /* XXX: entry point? */
164 return write_ith_record(f
, 0, 0, 1, NULL
);
167 static int write_srecord(FILE *f
, unsigned int len
, unsigned int alen
,
168 uint32_t addr
, uint8_t type
, void *data
)
170 char buf
[2+2+8+255*2+2+2];
172 uint8_t csum
, *dptr
= data
;
176 fprintf(stderr
, "%s: internal error: invalid srec record size\n",
191 fprintf(stderr
, "%s: internal error: invalid srec address length\n",
196 csum
= (len
+alen
+1) + addr
+ (addr
>> 8) + (addr
>> 16) + (addr
>> 24);
197 for (i
= 0; i
< len
; i
++)
201 p
+= sprintf(p
, "S%c%02X%0*X", type
, len
+alen
+1, alen
*2, addr
);
202 for (i
= 0; i
< len
; i
++)
203 p
+= sprintf(p
, "%02X", dptr
[i
]);
204 p
+= sprintf(p
, "%02X\n", csum
);
206 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
212 static int init_srec(FILE *f
)
214 return write_srecord(f
, 0, 2, 0, '0', NULL
);
217 static int fini_srec(FILE *f
)
219 /* XXX: entry point? */
220 return write_srecord(f
, 0, 4, 0, '7', NULL
);
223 static int output_srec(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
225 uint8_t *dbuf
= data
;
229 /* Output up to 32 bytes, but always end on an aligned boundary */
230 chunk
= 32 - (where
& 31);
234 if (write_srecord(f
, chunk
, 4, where
, '3', dbuf
))
244 static struct output_format output_formats
[] = {
245 { "bin", "wb", null_init_fini
, output_bin
, null_init_fini
},
246 { "com", "wb", com_init
, output_bin
, null_init_fini
},
247 { "ith", "wt", null_init_fini
, output_ith
, fini_ith
},
248 { "ihx", "wt", null_init_fini
, output_ith
, fini_ith
},
249 { "srec", "wt", init_srec
, output_srec
, fini_srec
},
250 { NULL
, NULL
, NULL
, NULL
, NULL
}
253 static const char *getformat(const char *pathname
)
256 static char fmt_buf
[16];
259 * Search backwards for the string "rdf2" followed by a string
260 * of alphanumeric characters. This should handle path prefixes,
261 * as well as extensions (e.g. C:\FOO\RDF2SREC.EXE).
263 for (p
= strchr(pathname
, '\0')-1 ; p
>= pathname
; p
--) {
264 if (!nasm_stricmp(p
, "rdf2")) {
267 while (isalnum(*q
) && r
< fmt_buf
+sizeof fmt_buf
-1)
277 static void usage(void)
280 "Usage: %s [options] input-file output-file\n"
282 " -o origin Specify the relocation origin\n"
283 " -p alignment Specify minimum segment alignment\n"
284 " -f format Select format (bin, com, ith, srec)\n"
290 int main(int argc
, char **argv
)
295 int codepad
, datapad
;
296 const char *format
= NULL
;
297 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
));