Subversion Repositories Kolibri OS

Rev

Rev 5197 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5197 serge 1
/* BFD back-end for verilog hex memory dump files.
6324 serge 2
   Copyright (C) 2009-2015 Free Software Foundation, Inc.
5197 serge 3
   Written by Anthony Green 
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
 
23
/* SUBSECTION
24
	Verilog hex memory file handling
25
 
26
   DESCRIPTION
27
 
28
	Verilog hex memory files cannot hold anything but addresses
29
	and data, so that's all that we implement.
30
 
31
	The syntax of the text file is described in the IEEE standard
32
	for Verilog.  Briefly, the file contains two types of tokens:
33
	data and optional addresses.  The tokens are separated by
34
	whitespace and comments.  Comments may be single line or
35
	multiline, using syntax similar to C++.  Addresses are
36
	specified by a leading "at" character (@) and are always
37
	hexadecimal strings.  Data and addresses may contain
38
	underscore (_) characters.
39
 
40
	If no address is specified, the data is assumed to start at
41
	address 0.  Similarly, if data exists before the first
42
	specified address, then that data is assumed to start at
43
	address 0.
44
 
45
 
46
   EXAMPLE
47
	@1000
48
        01 ae 3f 45 12
49
 
50
   DESCRIPTION
51
	@1000 specifies the starting address for the memory data.
52
	The following characters describe the 5 bytes at 0x1000.  */
53
 
54
 
55
#include "sysdep.h"
56
#include "bfd.h"
57
#include "libbfd.h"
58
#include "libiberty.h"
59
#include "safe-ctype.h"
60
 
61
/* Macros for converting between hex and binary.  */
62
 
63
static const char digs[] = "0123456789ABCDEF";
64
 
65
#define NIBBLE(x)    hex_value(x)
66
#define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
67
#define TOHEX(d, x) \
68
	d[1] = digs[(x) & 0xf]; \
69
	d[0] = digs[((x) >> 4) & 0xf];
70
 
71
/* When writing a verilog memory dump file, we write them in the order
72
   in which they appear in memory. This structure is used to hold them
73
   in memory.  */
74
 
75
struct verilog_data_list_struct
76
{
77
  struct verilog_data_list_struct *next;
78
  bfd_byte * data;
79
  bfd_vma where;
80
  bfd_size_type size;
81
};
82
 
83
typedef struct verilog_data_list_struct verilog_data_list_type;
84
 
85
/* The verilog tdata information.  */
86
 
87
typedef struct verilog_data_struct
88
{
89
  verilog_data_list_type *head;
90
  verilog_data_list_type *tail;
91
}
92
tdata_type;
93
 
94
static bfd_boolean
95
verilog_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
96
{
97
  if (arch != bfd_arch_unknown)
98
    return bfd_default_set_arch_mach (abfd, arch, mach);
99
 
100
  abfd->arch_info = & bfd_default_arch_struct;
101
  return TRUE;
102
}
103
 
104
/* We have to save up all the outpu for a splurge before output.  */
105
 
106
static bfd_boolean
107
verilog_set_section_contents (bfd *abfd,
108
			      sec_ptr section,
109
			      const void * location,
110
			      file_ptr offset,
111
			      bfd_size_type bytes_to_do)
112
{
113
  tdata_type *tdata = abfd->tdata.verilog_data;
114
  verilog_data_list_type *entry;
115
 
116
  entry = (verilog_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
117
  if (entry == NULL)
118
    return FALSE;
119
 
120
  if (bytes_to_do
121
      && (section->flags & SEC_ALLOC)
122
      && (section->flags & SEC_LOAD))
123
    {
124
      bfd_byte *data;
125
 
126
      data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
127
      if (data == NULL)
128
	return FALSE;
129
      memcpy ((void *) data, location, (size_t) bytes_to_do);
130
 
131
      entry->data = data;
132
      entry->where = section->lma + offset;
133
      entry->size = bytes_to_do;
134
 
135
      /* Sort the records by address.  Optimize for the common case of
136
	 adding a record to the end of the list.  */
137
      if (tdata->tail != NULL
138
	  && entry->where >= tdata->tail->where)
139
	{
140
	  tdata->tail->next = entry;
141
	  entry->next = NULL;
142
	  tdata->tail = entry;
143
	}
144
      else
145
	{
146
	  verilog_data_list_type **look;
147
 
148
	  for (look = &tdata->head;
149
	       *look != NULL && (*look)->where < entry->where;
150
	       look = &(*look)->next)
151
	    ;
152
	  entry->next = *look;
153
	  *look = entry;
154
	  if (entry->next == NULL)
155
	    tdata->tail = entry;
156
	}
157
    }
158
  return TRUE;
159
}
160
 
161
static bfd_boolean
162
verilog_write_address (bfd *abfd, bfd_vma address)
163
{
164
  char buffer[12];
165
  char *dst = buffer;
166
  bfd_size_type wrlen;
167
 
168
  /* Write the address.  */
169
  *dst++ = '@';
170
  TOHEX (dst, (address >> 24));
171
  dst += 2;
172
  TOHEX (dst, (address >> 16));
173
  dst += 2;
174
  TOHEX (dst, (address >> 8));
175
  dst += 2;
176
  TOHEX (dst, (address));
177
  dst += 2;
178
  *dst++ = '\r';
179
  *dst++ = '\n';
180
  wrlen = dst - buffer;
181
 
182
  return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
183
}
184
 
185
/* Write a record of type, of the supplied number of bytes. The
186
   supplied bytes and length don't have a checksum. That's worked out
187
   here.  */
188
 
189
static bfd_boolean
190
verilog_write_record (bfd *abfd,
191
		      const bfd_byte *data,
192
		      const bfd_byte *end)
193
{
6324 serge 194
  char buffer[50];
5197 serge 195
  const bfd_byte *src = data;
196
  char *dst = buffer;
197
  bfd_size_type wrlen;
198
 
199
  /* Write the data.  */
200
  for (src = data; src < end; src++)
201
    {
202
      TOHEX (dst, *src);
203
      dst += 2;
204
      *dst++ = ' ';
205
    }
206
  *dst++ = '\r';
207
  *dst++ = '\n';
208
  wrlen = dst - buffer;
209
 
210
  return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
211
}
212
 
213
static bfd_boolean
214
verilog_write_section (bfd *abfd,
215
		       tdata_type *tdata ATTRIBUTE_UNUSED,
216
		       verilog_data_list_type *list)
217
{
218
  unsigned int octets_written = 0;
219
  bfd_byte *location = list->data;
220
 
221
  verilog_write_address (abfd, list->where);
222
  while (octets_written < list->size)
223
    {
224
      unsigned int octets_this_chunk = list->size - octets_written;
225
 
226
      if (octets_this_chunk > 16)
227
	octets_this_chunk = 16;
228
 
229
      if (! verilog_write_record (abfd,
230
				  location,
231
				  location + octets_this_chunk))
232
	return FALSE;
233
 
234
      octets_written += octets_this_chunk;
235
      location += octets_this_chunk;
236
    }
237
 
238
  return TRUE;
239
}
240
 
241
static bfd_boolean
242
verilog_write_object_contents (bfd *abfd)
243
{
244
  tdata_type *tdata = abfd->tdata.verilog_data;
245
  verilog_data_list_type *list;
246
 
247
  /* Now wander though all the sections provided and output them.  */
248
  list = tdata->head;
249
 
250
  while (list != (verilog_data_list_type *) NULL)
251
    {
252
      if (! verilog_write_section (abfd, tdata, list))
253
	return FALSE;
254
      list = list->next;
255
    }
256
  return TRUE;
257
}
258
 
259
/* Initialize by filling in the hex conversion array.  */
260
 
261
static void
262
verilog_init (void)
263
{
264
  static bfd_boolean inited = FALSE;
265
 
266
  if (! inited)
267
    {
268
      inited = TRUE;
269
      hex_init ();
270
    }
271
}
272
 
273
/* Set up the verilog tdata information.  */
274
 
275
static bfd_boolean
276
verilog_mkobject (bfd *abfd)
277
{
278
  tdata_type *tdata;
279
 
280
  verilog_init ();
281
 
282
  tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
283
  if (tdata == NULL)
284
    return FALSE;
285
 
286
  abfd->tdata.verilog_data = tdata;
287
  tdata->head = NULL;
288
  tdata->tail = NULL;
289
 
290
  return TRUE;
291
}
292
 
293
#define	verilog_close_and_cleanup                    _bfd_generic_close_and_cleanup
294
#define verilog_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
295
#define verilog_new_section_hook                     _bfd_generic_new_section_hook
296
#define verilog_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
297
#define verilog_bfd_is_local_label_name              bfd_generic_is_local_label_name
298
#define verilog_get_lineno                           _bfd_nosymbols_get_lineno
299
#define verilog_find_nearest_line                    _bfd_nosymbols_find_nearest_line
300
#define verilog_find_inliner_info                    _bfd_nosymbols_find_inliner_info
301
#define verilog_make_empty_symbol                    _bfd_generic_make_empty_symbol
302
#define verilog_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
303
#define verilog_read_minisymbols                     _bfd_generic_read_minisymbols
304
#define verilog_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
305
#define verilog_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
306
#define verilog_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
307
#define verilog_bfd_relax_section                    bfd_generic_relax_section
308
#define verilog_bfd_gc_sections                      bfd_generic_gc_sections
309
#define verilog_bfd_merge_sections                   bfd_generic_merge_sections
310
#define verilog_bfd_is_group_section                 bfd_generic_is_group_section
311
#define verilog_bfd_discard_group                    bfd_generic_discard_group
312
#define verilog_section_already_linked               _bfd_generic_section_already_linked
313
#define verilog_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
314
#define verilog_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
315
#define verilog_bfd_link_just_syms                   _bfd_generic_link_just_syms
316
#define verilog_bfd_final_link                       _bfd_generic_final_link
317
#define verilog_bfd_link_split_section               _bfd_generic_link_split_section
318
 
319
const bfd_target verilog_vec =
320
{
321
  "verilog",			/* Name.  */
322
  bfd_target_verilog_flavour,
323
  BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
324
  BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
325
  (HAS_RELOC | EXEC_P |		/* Object flags.  */
326
   HAS_LINENO | HAS_DEBUG |
327
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
328
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
329
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
330
  0,				/* Leading underscore.  */
331
  ' ',				/* AR_pad_char.  */
332
  16,				/* AR_max_namelen.  */
333
  0,				/* match priority.  */
334
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
335
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
336
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
337
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
338
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
339
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
340
 
341
  {
342
    _bfd_dummy_target,
343
    _bfd_dummy_target,
344
    _bfd_dummy_target,
345
    _bfd_dummy_target,
346
  },
347
  {
348
    bfd_false,
349
    verilog_mkobject,
350
    bfd_false,
351
    bfd_false,
352
  },
353
  {				/* bfd_write_contents.  */
354
    bfd_false,
355
    verilog_write_object_contents,
356
    bfd_false,
357
    bfd_false,
358
  },
359
 
360
  BFD_JUMP_TABLE_GENERIC (_bfd_generic),
361
  BFD_JUMP_TABLE_COPY (_bfd_generic),
362
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
363
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
364
  BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
365
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
366
  BFD_JUMP_TABLE_WRITE (verilog),
367
  BFD_JUMP_TABLE_LINK (_bfd_nolink),
368
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
369
 
370
  NULL,
371
 
372
  NULL
373
};