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
;
92 if (fwrite(data
, 1, bytes
, f
) != bytes
)
99 static int write_ith_record(FILE *f
, unsigned int len
, uint16_t addr
,
100 uint8_t type
, void *data
)
102 char buf
[1+2+4+2+255*2+2+2];
104 uint8_t csum
, *dptr
= data
;
108 fprintf(stderr
, "%s: internal error: invalid ith record size\n",
113 csum
= len
+ addr
+ (addr
>> 8) + type
;
114 for (i
= 0; i
< len
; i
++)
118 p
+= sprintf(p
, ":%02X%04X%02X", len
, addr
, type
);
119 for (i
= 0; i
< len
; i
++)
120 p
+= sprintf(p
, "%02X", dptr
[i
]);
121 p
+= sprintf(p
, "%02X\n", csum
);
123 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
129 static int output_ith(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
131 static uint32_t last
= 0; /* Last address written */
133 uint8_t *dbuf
= data
;
137 if ((where
^ last
) & ~0xffff) {
138 abuf
[0] = where
>> 24;
139 abuf
[1] = where
>> 16;
140 if (write_ith_record(f
, 2, 0, 4, abuf
))
144 /* Output up to 32 bytes, but always end on an aligned boundary */
145 chunk
= 32 - (where
& 31);
149 if (write_ith_record(f
, chunk
, (uint16_t)where
, 0, dbuf
))
153 last
= where
+ chunk
- 1;
160 static int fini_ith(FILE *f
)
162 /* XXX: entry point? */
163 return write_ith_record(f
, 0, 0, 1, NULL
);
166 static int write_srecord(FILE *f
, unsigned int len
, unsigned int alen
,
167 uint32_t addr
, uint8_t type
, void *data
)
169 char buf
[2+2+8+255*2+2+2];
171 uint8_t csum
, *dptr
= data
;
175 fprintf(stderr
, "%s: internal error: invalid srec record size\n",
190 fprintf(stderr
, "%s: internal error: invalid srec address length\n",
195 csum
= (len
+alen
+1) + addr
+ (addr
>> 8) + (addr
>> 16) + (addr
>> 24);
196 for (i
= 0; i
< len
; i
++)
200 p
+= sprintf(p
, "S%c%02X%0*X", type
, len
+alen
+1, alen
*2, addr
);
201 for (i
= 0; i
< len
; i
++)
202 p
+= sprintf(p
, "%02X", dptr
[i
]);
203 p
+= sprintf(p
, "%02X\n", csum
);
205 if (fwrite(buf
, 1, p
-buf
, f
) != (size_t)(p
-buf
))
211 static int init_srec(FILE *f
)
213 return write_srecord(f
, 0, 2, 0, '0', NULL
);
216 static int fini_srec(FILE *f
)
218 /* XXX: entry point? */
219 return write_srecord(f
, 0, 4, 0, '7', NULL
);
222 static int output_srec(FILE *f
, void *data
, uint32_t bytes
, uint32_t where
)
224 uint8_t *dbuf
= data
;
228 /* Output up to 32 bytes, but always end on an aligned boundary */
229 chunk
= 32 - (where
& 31);
233 if (write_srecord(f
, chunk
, 4, where
, '3', dbuf
))
243 static struct output_format output_formats
[] = {
244 { "bin", "wb", null_init_fini
, output_bin
, null_init_fini
},
245 { "com", "wb", com_init
, output_bin
, null_init_fini
},
246 { "ith", "wt", null_init_fini
, output_ith
, fini_ith
},
247 { "ihx", "wt", null_init_fini
, output_ith
, fini_ith
},
248 { "srec", "wt", init_srec
, output_srec
, fini_srec
},
249 { NULL
, NULL
, NULL
, NULL
, NULL
}
252 static const char *getformat(const char *pathname
)
255 static char fmt_buf
[16];
258 * Search backwards for the string "rdf2" followed by a string
259 * of alphanumeric characters. This should handle path prefixes,
260 * as well as extensions (e.g. C:\FOO\RDF2SREC.EXE).
262 for (p
= strchr(pathname
, '\0')-1 ; p
>= pathname
; p
--) {
263 if (!nasm_stricmp(p
, "rdf2")) {
266 while (isalnum(*q
) && r
< fmt_buf
+sizeof fmt_buf
-1)
276 static void usage(void)
279 "Usage: %s [options] input-file output-file\n"
281 " -o origin Specify the relocation origin\n"
282 " -p alignment Specify minimum segment alignment\n"
283 " -f format Select format (bin, com, ith, srec)\n"
289 int main(int argc
, char **argv
)
294 int codepad
, datapad
;
295 const char *format
= NULL
;
296 const struct output_format
*fmt
;
311 if (argv
[0][0] == '-' && argv
[0][1] && !argv
[0][2]) {
312 switch (argv
[0][1]) {
315 origin
= readnum(*argv
, &err
);
317 fprintf(stderr
, "%s: invalid parameter: %s\n",
325 align
= readnum(*argv
, &err
);
327 fprintf(stderr
, "%s: invalid parameter: %s\n",
347 fprintf(stderr
, "%s: unknown option: %s\n",
361 format
= getformat(progname
);
364 fprintf(stderr
, "%s: unable to determine desired output format\n",
369 for (fmt
= output_formats
; fmt
->name
; fmt
++) {
370 if (!nasm_stricmp(format
, fmt
->name
))
375 fprintf(stderr
, "%s: unknown output format: %s\n", progname
, format
);
382 rdfperror(progname
, *argv
);
387 printf("relocating %s: origin=%"PRIx32
", align=%d\n",
388 *argv
, origin
, align
);
391 m
->datarel
= origin
+ m
->f
.seg
[0].length
;
392 if (m
->datarel
% align
!= 0) {
393 codepad
= align
- (m
->datarel
% align
);
394 m
->datarel
+= codepad
;
398 m
->bssrel
= m
->datarel
+ m
->f
.seg
[1].length
;
399 if (m
->bssrel
% align
!= 0) {
400 datapad
= align
- (m
->bssrel
% align
);
401 m
->bssrel
+= datapad
;
406 printf("code: %08"PRIx32
"\ndata: %08"PRIx32
"\nbss: %08"PRIx32
"\n",
407 m
->textrel
, m
->datarel
, m
->bssrel
);
413 of
= fopen(*argv
, fmt
->mode
);
415 fprintf(stderr
, "%s: could not open output file %s: %s\n",
416 progname
, *argv
, strerror(errno
));
421 fmt
->output(of
, m
->t
, m
->f
.seg
[0].length
, m
->textrel
) ||
422 fmt
->output(of
, m
->d
, m
->f
.seg
[1].length
, m
->datarel
) ||
424 fprintf(stderr
, "%s: error writing to %s: %s\n",
425 progname
, *argv
, strerror(errno
));