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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [ppcboot.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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