OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [ppcboot.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* BFD back-end for PPCbug boot records.
2
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
3
   Free Software Foundation, Inc.
4
   Written by Michael Meissner, Cygnus Support, <meissner@cygnus.com>
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
/* This is a BFD backend which may be used to write PowerPCBug boot objects.
23
   It may only be used for output, not input.  The intention is that this may
24
   be used as an output format for objcopy in order to generate raw binary
25
   data.
26
 
27
   This is very simple.  The only complication is that the real data
28
   will start at some address X, and in some cases we will not want to
29
   include X zeroes just to get to that point.  Since the start
30
   address is not meaningful for this object file format, we use it
31
   instead to indicate the number of zeroes to skip at the start of
32
   the file.  objcopy cooperates by specially setting the start
33
   address to zero by default.  */
34
 
35
#include "safe-ctype.h"
36
#include "bfd.h"
37
#include "sysdep.h"
38
#include "libbfd.h"
39
 
40
/* PPCbug location structure */
41
typedef struct ppcboot_location {
42
  bfd_byte      ind;
43
  bfd_byte      head;
44
  bfd_byte      sector;
45
  bfd_byte      cylinder;
46
} ppcboot_location_t;
47
 
48
/* PPCbug partition table layout */
49
typedef struct ppcboot_partition {
50
  ppcboot_location_t    partition_begin;        /* partition begin */
51
  ppcboot_location_t    partition_end;          /* partition end */
52
  bfd_byte              sector_begin[4];        /* 32-bit start RBA (zero-based), little endian */
53
  bfd_byte              sector_length[4];       /* 32-bit RBA count (one-based), little endian */
54
} ppcboot_partition_t;
55
 
56
/* PPCbug boot layout.  */
57
typedef struct ppcboot_hdr {
58
  bfd_byte              pc_compatibility[446];  /* x86 instruction field */
59
  ppcboot_partition_t   partition[4];           /* partition information */
60
  bfd_byte              signature[2];           /* 0x55 and 0xaa */
61
  bfd_byte              entry_offset[4];        /* entry point offset, little endian */
62
  bfd_byte              length[4];              /* load image length, little endian */
63
  bfd_byte              flags;                  /* flag field */
64
  bfd_byte              os_id;                  /* OS_ID */
65
  char                  partition_name[32];     /* partition name */
66
  bfd_byte              reserved1[470];         /* reserved */
67
}
68
#ifdef __GNUC__
69
  __attribute__ ((packed))
70
#endif
71
ppcboot_hdr_t;
72
 
73
/* Signature bytes for last 2 bytes of the 512 byte record */
74
#define SIGNATURE0 0x55
75
#define SIGNATURE1 0xaa
76
 
77
/* PowerPC boot type */
78
#define PPC_IND 0x41
79
 
80
/* Information needed for ppcboot header */
81
typedef struct ppcboot_data {
82
  ppcboot_hdr_t header;                         /* raw header */
83
  asection *sec;                                /* single section */
84
} ppcboot_data_t;
85
 
86
/* Any bfd we create by reading a ppcboot file has three symbols:
87
   a start symbol, an end symbol, and an absolute length symbol.  */
88
#define PPCBOOT_SYMS 3
89
 
90
static boolean ppcboot_mkobject PARAMS ((bfd *));
91
static const bfd_target *ppcboot_object_p PARAMS ((bfd *));
92
static boolean ppcboot_set_arch_mach
93
  PARAMS ((bfd *, enum bfd_architecture, unsigned long));
94
static boolean ppcboot_get_section_contents
95
  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
96
static long ppcboot_get_symtab_upper_bound PARAMS ((bfd *));
97
static char *mangle_name PARAMS ((bfd *, char *));
98
static long ppcboot_get_symtab PARAMS ((bfd *, asymbol **));
99
static void ppcboot_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
100
static boolean ppcboot_set_section_contents
101
  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
102
static int ppcboot_sizeof_headers PARAMS ((bfd *, boolean));
103
static boolean ppcboot_bfd_print_private_bfd_data PARAMS ((bfd *, PTR));
104
 
105
#define ppcboot_set_tdata(abfd, ptr) ((abfd)->tdata.any = (PTR) (ptr))
106
#define ppcboot_get_tdata(abfd) ((ppcboot_data_t *) ((abfd)->tdata.any))
107
 
108
/* Create a ppcboot object.  Invoked via bfd_set_format.  */
109
 
110
static boolean
111
ppcboot_mkobject (abfd)
112
     bfd *abfd;
113
{
114
  if (!ppcboot_get_tdata (abfd))
115
    {
116
      bfd_size_type amt = sizeof (ppcboot_data_t);
117
      ppcboot_set_tdata (abfd, bfd_zalloc (abfd, amt));
118
    }
119
 
120
  return true;
121
}
122
 
123
 
124
/* Set the architecture to PowerPC */
125
static boolean
126
ppcboot_set_arch_mach (abfd, arch, machine)
127
     bfd *abfd;
128
     enum bfd_architecture arch;
129
     unsigned long machine;
130
{
131
  if (arch == bfd_arch_unknown)
132
    arch = bfd_arch_powerpc;
133
 
134
  else if (arch != bfd_arch_powerpc)
135
    return false;
136
 
137
  return bfd_default_set_arch_mach (abfd, arch, machine);
138
}
139
 
140
 
141
/* Any file may be considered to be a ppcboot file, provided the target
142
   was not defaulted.  That is, it must be explicitly specified as
143
   being ppcboot.  */
144
 
145
static const bfd_target *
146
ppcboot_object_p (abfd)
147
     bfd *abfd;
148
{
149
  struct stat statbuf;
150
  asection *sec;
151
  ppcboot_hdr_t hdr;
152
  size_t i;
153
  ppcboot_data_t *tdata;
154
 
155
  BFD_ASSERT (sizeof (ppcboot_hdr_t) == 1024);
156
 
157
  if (abfd->target_defaulted)
158
    {
159
      bfd_set_error (bfd_error_wrong_format);
160
      return NULL;
161
    }
162
 
163
  /* Find the file size.  */
164
  if (bfd_stat (abfd, &statbuf) < 0)
165
    {
166
      bfd_set_error (bfd_error_system_call);
167
      return NULL;
168
    }
169
 
170
  if ((size_t) statbuf.st_size < sizeof (ppcboot_hdr_t))
171
    {
172
      bfd_set_error (bfd_error_wrong_format);
173
      return NULL;
174
    }
175
 
176
  if (bfd_bread ((PTR) &hdr, (bfd_size_type) sizeof (hdr), abfd)
177
      != sizeof (hdr))
178
    {
179
      if (bfd_get_error () != bfd_error_system_call)
180
        bfd_set_error (bfd_error_wrong_format);
181
 
182
      return NULL;
183
    }
184
 
185
  /* Now do some basic checks.  */
186
  for (i = 0; i < sizeof (hdr.pc_compatibility); i++)
187
    if (hdr.pc_compatibility[i])
188
      {
189
        bfd_set_error (bfd_error_wrong_format);
190
        return NULL;
191
      }
192
 
193
  if (hdr.signature[0] != SIGNATURE0 || hdr.signature[1] != SIGNATURE1)
194
    {
195
      bfd_set_error (bfd_error_wrong_format);
196
      return NULL;
197
    }
198
 
199
  if (hdr.partition[0].partition_end.ind != PPC_IND)
200
    {
201
      bfd_set_error (bfd_error_wrong_format);
202
      return NULL;
203
    }
204
 
205
  abfd->symcount = PPCBOOT_SYMS;
206
 
207
  /* One data section.  */
208
  sec = bfd_make_section (abfd, ".data");
209
  if (sec == NULL)
210
    return NULL;
211
  sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_CODE | SEC_HAS_CONTENTS;
212
  sec->vma = 0;
213
  sec->_raw_size = statbuf.st_size - sizeof (ppcboot_hdr_t);
214
  sec->filepos = sizeof (ppcboot_hdr_t);
215
 
216
  ppcboot_mkobject (abfd);
217
  tdata = ppcboot_get_tdata (abfd);
218
  tdata->sec = sec;
219
  memcpy ((PTR) &tdata->header, (PTR) &hdr, sizeof (ppcboot_hdr_t));
220
 
221
  ppcboot_set_arch_mach (abfd, bfd_arch_powerpc, 0L);
222
  return abfd->xvec;
223
}
224
 
225
#define ppcboot_close_and_cleanup _bfd_generic_close_and_cleanup
226
#define ppcboot_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
227
#define ppcboot_new_section_hook _bfd_generic_new_section_hook
228
 
229
 
230
/* Get contents of the only section.  */
231
 
232
static boolean
233
ppcboot_get_section_contents (abfd, section, location, offset, count)
234
     bfd *abfd;
235
     asection *section ATTRIBUTE_UNUSED;
236
     PTR location;
237
     file_ptr offset;
238
     bfd_size_type count;
239
{
240
  if (bfd_seek (abfd, offset + (file_ptr) sizeof (ppcboot_hdr_t), SEEK_SET) != 0
241
      || bfd_bread (location, count, abfd) != count)
242
    return false;
243
  return true;
244
}
245
 
246
 
247
/* Return the amount of memory needed to read the symbol table.  */
248
 
249
static long
250
ppcboot_get_symtab_upper_bound (abfd)
251
     bfd *abfd ATTRIBUTE_UNUSED;
252
{
253
  return (PPCBOOT_SYMS + 1) * sizeof (asymbol *);
254
}
255
 
256
 
257
/* Create a symbol name based on the bfd's filename.  */
258
 
259
static char *
260
mangle_name (abfd, suffix)
261
     bfd *abfd;
262
     char *suffix;
263
{
264
  bfd_size_type size;
265
  char *buf;
266
  char *p;
267
 
268
  size = (strlen (bfd_get_filename (abfd))
269
          + strlen (suffix)
270
          + sizeof "_ppcboot__");
271
 
272
  buf = (char *) bfd_alloc (abfd, size);
273
  if (buf == NULL)
274
    return "";
275
 
276
  sprintf (buf, "_ppcboot_%s_%s", bfd_get_filename (abfd), suffix);
277
 
278
  /* Change any non-alphanumeric characters to underscores.  */
279
  for (p = buf; *p; p++)
280
    if (! ISALNUM (*p))
281
      *p = '_';
282
 
283
  return buf;
284
}
285
 
286
 
287
/* Return the symbol table.  */
288
 
289
static long
290
ppcboot_get_symtab (abfd, alocation)
291
     bfd *abfd;
292
     asymbol **alocation;
293
{
294
  asection *sec = ppcboot_get_tdata (abfd)->sec;
295
  asymbol *syms;
296
  unsigned int i;
297
  bfd_size_type amt = PPCBOOT_SYMS * sizeof (asymbol);
298
 
299
  syms = (asymbol *) bfd_alloc (abfd, amt);
300
  if (syms == NULL)
301
    return false;
302
 
303
  /* Start symbol.  */
304
  syms[0].the_bfd = abfd;
305
  syms[0].name = mangle_name (abfd, "start");
306
  syms[0].value = 0;
307
  syms[0].flags = BSF_GLOBAL;
308
  syms[0].section = sec;
309
  syms[0].udata.p = NULL;
310
 
311
  /* End symbol.  */
312
  syms[1].the_bfd = abfd;
313
  syms[1].name = mangle_name (abfd, "end");
314
  syms[1].value = sec->_raw_size;
315
  syms[1].flags = BSF_GLOBAL;
316
  syms[1].section = sec;
317
  syms[1].udata.p = NULL;
318
 
319
  /* Size symbol.  */
320
  syms[2].the_bfd = abfd;
321
  syms[2].name = mangle_name (abfd, "size");
322
  syms[2].value = sec->_raw_size;
323
  syms[2].flags = BSF_GLOBAL;
324
  syms[2].section = bfd_abs_section_ptr;
325
  syms[2].udata.p = NULL;
326
 
327
  for (i = 0; i < PPCBOOT_SYMS; i++)
328
    *alocation++ = syms++;
329
  *alocation = NULL;
330
 
331
  return PPCBOOT_SYMS;
332
}
333
 
334
#define ppcboot_make_empty_symbol _bfd_generic_make_empty_symbol
335
#define ppcboot_print_symbol _bfd_nosymbols_print_symbol
336
 
337
/* Get information about a symbol.  */
338
 
339
static void
340
ppcboot_get_symbol_info (ignore_abfd, symbol, ret)
341
     bfd *ignore_abfd ATTRIBUTE_UNUSED;
342
     asymbol *symbol;
343
     symbol_info *ret;
344
{
345
  bfd_symbol_info (symbol, ret);
346
}
347
 
348
#define ppcboot_bfd_is_local_label_name bfd_generic_is_local_label_name
349
#define ppcboot_get_lineno _bfd_nosymbols_get_lineno
350
#define ppcboot_find_nearest_line _bfd_nosymbols_find_nearest_line
351
#define ppcboot_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
352
#define ppcboot_read_minisymbols _bfd_generic_read_minisymbols
353
#define ppcboot_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
354
 
355
#define ppcboot_get_reloc_upper_bound \
356
  ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
357
#define ppcboot_canonicalize_reloc \
358
  ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
359
#define ppcboot_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
360
 
361
/* Write section contents of a ppcboot file.  */
362
 
363
static boolean
364
ppcboot_set_section_contents (abfd, sec, data, offset, size)
365
     bfd *abfd;
366
     asection *sec;
367
     PTR data;
368
     file_ptr offset;
369
     bfd_size_type size;
370
{
371
  if (! abfd->output_has_begun)
372
    {
373
      bfd_vma low;
374
      asection *s;
375
 
376
      /* The lowest section VMA sets the virtual address of the start
377
         of the file.  We use the set the file position of all the
378
         sections.  */
379
      low = abfd->sections->vma;
380
      for (s = abfd->sections->next; s != NULL; s = s->next)
381
        if (s->vma < low)
382
          low = s->vma;
383
 
384
      for (s = abfd->sections; s != NULL; s = s->next)
385
        s->filepos = s->vma - low;
386
 
387
      abfd->output_has_begun = true;
388
    }
389
 
390
  return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
391
}
392
 
393
 
394
static int
395
ppcboot_sizeof_headers (abfd, exec)
396
     bfd *abfd ATTRIBUTE_UNUSED;
397
     boolean exec ATTRIBUTE_UNUSED;
398
{
399
  return sizeof (ppcboot_hdr_t);
400
}
401
 
402
 
403
/* Print out the program headers.  */
404
 
405
static boolean
406
ppcboot_bfd_print_private_bfd_data (abfd, farg)
407
     bfd *abfd;
408
     PTR farg;
409
{
410
  FILE *f = (FILE *)farg;
411
  ppcboot_data_t *tdata = ppcboot_get_tdata (abfd);
412
  long entry_offset = bfd_getl_signed_32 ((PTR) tdata->header.entry_offset);
413
  long length = bfd_getl_signed_32 ((PTR) tdata->header.length);
414
  int i;
415
 
416
  fprintf (f, _("\nppcboot header:\n"));
417
  fprintf (f, _("Entry offset        = 0x%.8lx (%ld)\n"), entry_offset, entry_offset);
418
  fprintf (f, _("Length              = 0x%.8lx (%ld)\n"), length, length);
419
 
420
  if (tdata->header.flags)
421
    fprintf (f, _("Flag field          = 0x%.2x\n"), tdata->header.flags);
422
 
423
  if (tdata->header.os_id)
424
    fprintf (f, "OS_ID               = 0x%.2x\n", tdata->header.os_id);
425
 
426
  if (tdata->header.partition_name)
427
    fprintf (f, _("Partition name      = \"%s\"\n"), tdata->header.partition_name);
428
 
429
  for (i = 0; i < 4; i++)
430
    {
431
      long sector_begin  = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_begin);
432
      long sector_length = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_length);
433
 
434
      /* Skip all 0 entries */
435
      if (!tdata->header.partition[i].partition_begin.ind
436
          && !tdata->header.partition[i].partition_begin.head
437
          && !tdata->header.partition[i].partition_begin.sector
438
          && !tdata->header.partition[i].partition_begin.cylinder
439
          && !tdata->header.partition[i].partition_end.ind
440
          && !tdata->header.partition[i].partition_end.head
441
          && !tdata->header.partition[i].partition_end.sector
442
          && !tdata->header.partition[i].partition_end.cylinder
443
          && !sector_begin && !sector_length)
444
        continue;
445
 
446
      fprintf (f, _("\nPartition[%d] start  = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
447
               tdata->header.partition[i].partition_begin.ind,
448
               tdata->header.partition[i].partition_begin.head,
449
               tdata->header.partition[i].partition_begin.sector,
450
               tdata->header.partition[i].partition_begin.cylinder);
451
 
452
      fprintf (f, _("Partition[%d] end    = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
453
               tdata->header.partition[i].partition_end.ind,
454
               tdata->header.partition[i].partition_end.head,
455
               tdata->header.partition[i].partition_end.sector,
456
               tdata->header.partition[i].partition_end.cylinder);
457
 
458
      fprintf (f, _("Partition[%d] sector = 0x%.8lx (%ld)\n"), i, sector_begin, sector_begin);
459
      fprintf (f, _("Partition[%d] length = 0x%.8lx (%ld)\n"), i, sector_length, sector_length);
460
    }
461
 
462
  fprintf (f, "\n");
463
  return true;
464
}
465
 
466
 
467
#define ppcboot_bfd_get_relocated_section_contents \
468
  bfd_generic_get_relocated_section_contents
469
#define ppcboot_bfd_relax_section bfd_generic_relax_section
470
#define ppcboot_bfd_gc_sections bfd_generic_gc_sections
471
#define ppcboot_bfd_merge_sections bfd_generic_merge_sections
472
#define ppcboot_bfd_discard_group bfd_generic_discard_group
473
#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
474
#define ppcboot_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
475
#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
476
#define ppcboot_bfd_link_just_syms _bfd_generic_link_just_syms
477
#define ppcboot_bfd_final_link _bfd_generic_final_link
478
#define ppcboot_bfd_link_split_section _bfd_generic_link_split_section
479
#define ppcboot_get_section_contents_in_window \
480
  _bfd_generic_get_section_contents_in_window
481
 
482
#define ppcboot_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
483
#define ppcboot_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
484
#define ppcboot_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
485
#define ppcboot_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
486
#define ppcboot_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
487
#define ppcboot_bfd_print_private_bfd_dat ppcboot_bfd_print_private_bfd_data
488
 
489
const bfd_target ppcboot_vec =
490
{
491
  "ppcboot",                    /* name */
492
  bfd_target_unknown_flavour,   /* flavour */
493
  BFD_ENDIAN_BIG,               /* byteorder is big endian for code */
494
  BFD_ENDIAN_LITTLE,            /* header_byteorder */
495
  EXEC_P,                       /* object_flags */
496
  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
497
   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
498
  0,                             /* symbol_leading_char */
499
  ' ',                          /* ar_pad_char */
500
  16,                           /* ar_max_namelen */
501
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
502
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
503
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
504
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
505
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
506
  bfd_getl16, bfd_getl_signed_16, bfd_putl16,   /* hdrs */
507
  {                             /* bfd_check_format */
508
    _bfd_dummy_target,
509
    ppcboot_object_p,           /* bfd_check_format */
510
    _bfd_dummy_target,
511
    _bfd_dummy_target,
512
  },
513
  {                             /* bfd_set_format */
514
    bfd_false,
515
    ppcboot_mkobject,
516
    bfd_false,
517
    bfd_false,
518
  },
519
  {                             /* bfd_write_contents */
520
    bfd_false,
521
    bfd_true,
522
    bfd_false,
523
    bfd_false,
524
  },
525
 
526
  BFD_JUMP_TABLE_GENERIC (ppcboot),
527
  BFD_JUMP_TABLE_COPY (ppcboot),
528
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
529
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
530
  BFD_JUMP_TABLE_SYMBOLS (ppcboot),
531
  BFD_JUMP_TABLE_RELOCS (ppcboot),
532
  BFD_JUMP_TABLE_WRITE (ppcboot),
533
  BFD_JUMP_TABLE_LINK (ppcboot),
534
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
535
 
536
  NULL,
537
 
538
  NULL
539
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.