source: trunk/src/binutils/bfd/ppcboot.c@ 657

Last change on this file since 657 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.4 KB
Line 
1/* 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
6This file is part of BFD, the Binary File Descriptor library.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, 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 */
41typedef 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 */
49typedef 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. */
57typedef 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
71ppcboot_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 */
81typedef 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
90static bfd_boolean ppcboot_mkobject PARAMS ((bfd *));
91static const bfd_target *ppcboot_object_p PARAMS ((bfd *));
92static bfd_boolean ppcboot_set_arch_mach
93 PARAMS ((bfd *, enum bfd_architecture, unsigned long));
94static bfd_boolean ppcboot_get_section_contents
95 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
96static long ppcboot_get_symtab_upper_bound PARAMS ((bfd *));
97static char *mangle_name PARAMS ((bfd *, char *));
98static long ppcboot_get_symtab PARAMS ((bfd *, asymbol **));
99static void ppcboot_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
100static bfd_boolean ppcboot_set_section_contents
101 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
102static int ppcboot_sizeof_headers PARAMS ((bfd *, bfd_boolean));
103static bfd_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
109/* Create a ppcboot object. Invoked via bfd_set_format. */
110
111static bfd_boolean
112ppcboot_mkobject (abfd)
113 bfd *abfd;
114{
115 if (!ppcboot_get_tdata (abfd))
116 {
117 bfd_size_type amt = sizeof (ppcboot_data_t);
118 ppcboot_set_tdata (abfd, bfd_zalloc (abfd, amt));
119 }
120
121 return TRUE;
122}
123
124
125
126/* Set the architecture to PowerPC */
127static bfd_boolean
128ppcboot_set_arch_mach (abfd, arch, machine)
129 bfd *abfd;
130 enum bfd_architecture arch;
131 unsigned long machine;
132{
133 if (arch == bfd_arch_unknown)
134 arch = bfd_arch_powerpc;
135
136 else if (arch != bfd_arch_powerpc)
137 return FALSE;
138
139 return bfd_default_set_arch_mach (abfd, arch, machine);
140}
141
142
143
144/* Any file may be considered to be a ppcboot file, provided the target
145 was not defaulted. That is, it must be explicitly specified as
146 being ppcboot. */
147
148static const bfd_target *
149ppcboot_object_p (abfd)
150 bfd *abfd;
151{
152 struct stat statbuf;
153 asection *sec;
154 ppcboot_hdr_t hdr;
155 size_t i;
156 ppcboot_data_t *tdata;
157
158 BFD_ASSERT (sizeof (ppcboot_hdr_t) == 1024);
159
160 if (abfd->target_defaulted)
161 {
162 bfd_set_error (bfd_error_wrong_format);
163 return NULL;
164 }
165
166 /* Find the file size. */
167 if (bfd_stat (abfd, &statbuf) < 0)
168 {
169 bfd_set_error (bfd_error_system_call);
170 return NULL;
171 }
172
173 if ((size_t) statbuf.st_size < sizeof (ppcboot_hdr_t))
174 {
175 bfd_set_error (bfd_error_wrong_format);
176 return NULL;
177 }
178
179 if (bfd_bread ((PTR) &hdr, (bfd_size_type) sizeof (hdr), abfd)
180 != sizeof (hdr))
181 {
182 if (bfd_get_error () != bfd_error_system_call)
183 bfd_set_error (bfd_error_wrong_format);
184
185 return NULL;
186 }
187
188 /* Now do some basic checks. */
189 for (i = 0; i < sizeof (hdr.pc_compatibility); i++)
190 if (hdr.pc_compatibility[i])
191 {
192 bfd_set_error (bfd_error_wrong_format);
193 return NULL;
194 }
195
196 if (hdr.signature[0] != SIGNATURE0 || hdr.signature[1] != SIGNATURE1)
197 {
198 bfd_set_error (bfd_error_wrong_format);
199 return NULL;
200 }
201
202 if (hdr.partition[0].partition_end.ind != PPC_IND)
203 {
204 bfd_set_error (bfd_error_wrong_format);
205 return NULL;
206 }
207
208 abfd->symcount = PPCBOOT_SYMS;
209
210 /* One data section. */
211 sec = bfd_make_section (abfd, ".data");
212 if (sec == NULL)
213 return NULL;
214 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_CODE | SEC_HAS_CONTENTS;
215 sec->vma = 0;
216 sec->_raw_size = statbuf.st_size - sizeof (ppcboot_hdr_t);
217 sec->filepos = sizeof (ppcboot_hdr_t);
218
219 ppcboot_mkobject (abfd);
220 tdata = ppcboot_get_tdata (abfd);
221 tdata->sec = sec;
222 memcpy ((PTR) &tdata->header, (PTR) &hdr, sizeof (ppcboot_hdr_t));
223
224 ppcboot_set_arch_mach (abfd, bfd_arch_powerpc, 0L);
225 return abfd->xvec;
226}
227
228#define ppcboot_close_and_cleanup _bfd_generic_close_and_cleanup
229#define ppcboot_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
230#define ppcboot_new_section_hook _bfd_generic_new_section_hook
231
232
233
234/* Get contents of the only section. */
235
236static bfd_boolean
237ppcboot_get_section_contents (abfd, section, location, offset, count)
238 bfd *abfd;
239 asection *section ATTRIBUTE_UNUSED;
240 PTR location;
241 file_ptr offset;
242 bfd_size_type count;
243{
244 if (bfd_seek (abfd, offset + (file_ptr) sizeof (ppcboot_hdr_t), SEEK_SET) != 0
245 || bfd_bread (location, count, abfd) != count)
246 return FALSE;
247 return TRUE;
248}
249
250
251
252/* Return the amount of memory needed to read the symbol table. */
253
254static long
255ppcboot_get_symtab_upper_bound (abfd)
256 bfd *abfd ATTRIBUTE_UNUSED;
257{
258 return (PPCBOOT_SYMS + 1) * sizeof (asymbol *);
259}
260
261
262
263/* Create a symbol name based on the bfd's filename. */
264
265static char *
266mangle_name (abfd, suffix)
267 bfd *abfd;
268 char *suffix;
269{
270 bfd_size_type size;
271 char *buf;
272 char *p;
273
274 size = (strlen (bfd_get_filename (abfd))
275 + strlen (suffix)
276 + sizeof "_ppcboot__");
277
278 buf = (char *) bfd_alloc (abfd, size);
279 if (buf == NULL)
280 return "";
281
282 sprintf (buf, "_ppcboot_%s_%s", bfd_get_filename (abfd), suffix);
283
284 /* Change any non-alphanumeric characters to underscores. */
285 for (p = buf; *p; p++)
286 if (! ISALNUM (*p))
287 *p = '_';
288
289 return buf;
290}
291
292
293
294/* Return the symbol table. */
295
296static long
297ppcboot_get_symtab (abfd, alocation)
298 bfd *abfd;
299 asymbol **alocation;
300{
301 asection *sec = ppcboot_get_tdata (abfd)->sec;
302 asymbol *syms;
303 unsigned int i;
304 bfd_size_type amt = PPCBOOT_SYMS * sizeof (asymbol);
305
306 syms = (asymbol *) bfd_alloc (abfd, amt);
307 if (syms == NULL)
308 return FALSE;
309
310 /* Start symbol. */
311 syms[0].the_bfd = abfd;
312 syms[0].name = mangle_name (abfd, "start");
313 syms[0].value = 0;
314 syms[0].flags = BSF_GLOBAL;
315 syms[0].section = sec;
316 syms[0].udata.p = NULL;
317
318 /* End symbol. */
319 syms[1].the_bfd = abfd;
320 syms[1].name = mangle_name (abfd, "end");
321 syms[1].value = sec->_raw_size;
322 syms[1].flags = BSF_GLOBAL;
323 syms[1].section = sec;
324 syms[1].udata.p = NULL;
325
326 /* Size symbol. */
327 syms[2].the_bfd = abfd;
328 syms[2].name = mangle_name (abfd, "size");
329 syms[2].value = sec->_raw_size;
330 syms[2].flags = BSF_GLOBAL;
331 syms[2].section = bfd_abs_section_ptr;
332 syms[2].udata.p = NULL;
333
334 for (i = 0; i < PPCBOOT_SYMS; i++)
335 *alocation++ = syms++;
336 *alocation = NULL;
337
338 return PPCBOOT_SYMS;
339}
340
341#define ppcboot_make_empty_symbol _bfd_generic_make_empty_symbol
342#define ppcboot_print_symbol _bfd_nosymbols_print_symbol
343
344/* Get information about a symbol. */
345
346static void
347ppcboot_get_symbol_info (ignore_abfd, symbol, ret)
348 bfd *ignore_abfd ATTRIBUTE_UNUSED;
349 asymbol *symbol;
350 symbol_info *ret;
351{
352 bfd_symbol_info (symbol, ret);
353}
354
355#define ppcboot_bfd_is_local_label_name bfd_generic_is_local_label_name
356#define ppcboot_get_lineno _bfd_nosymbols_get_lineno
357#define ppcboot_find_nearest_line _bfd_nosymbols_find_nearest_line
358#define ppcboot_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
359#define ppcboot_read_minisymbols _bfd_generic_read_minisymbols
360#define ppcboot_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
361
362#define ppcboot_get_reloc_upper_bound \
363 ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
364#define ppcboot_canonicalize_reloc \
365 ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
366#define ppcboot_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
367
368
369/* Write section contents of a ppcboot file. */
370
371static bfd_boolean
372ppcboot_set_section_contents (abfd, sec, data, offset, size)
373 bfd *abfd;
374 asection *sec;
375 PTR data;
376 file_ptr offset;
377 bfd_size_type size;
378{
379 if (! abfd->output_has_begun)
380 {
381 bfd_vma low;
382 asection *s;
383
384 /* The lowest section VMA sets the virtual address of the start
385 of the file. We use the set the file position of all the
386 sections. */
387 low = abfd->sections->vma;
388 for (s = abfd->sections->next; s != NULL; s = s->next)
389 if (s->vma < low)
390 low = s->vma;
391
392 for (s = abfd->sections; s != NULL; s = s->next)
393 s->filepos = s->vma - low;
394
395 abfd->output_has_begun = TRUE;
396 }
397
398 return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
399}
400
401
402
403static int
404ppcboot_sizeof_headers (abfd, exec)
405 bfd *abfd ATTRIBUTE_UNUSED;
406 bfd_boolean exec ATTRIBUTE_UNUSED;
407{
408 return sizeof (ppcboot_hdr_t);
409}
410
411
412
413/* Print out the program headers. */
414
415static bfd_boolean
416ppcboot_bfd_print_private_bfd_data (abfd, farg)
417 bfd *abfd;
418 PTR farg;
419{
420 FILE *f = (FILE *)farg;
421 ppcboot_data_t *tdata = ppcboot_get_tdata (abfd);
422 long entry_offset = bfd_getl_signed_32 ((PTR) tdata->header.entry_offset);
423 long length = bfd_getl_signed_32 ((PTR) tdata->header.length);
424 int i;
425
426 fprintf (f, _("\nppcboot header:\n"));
427 fprintf (f, _("Entry offset = 0x%.8lx (%ld)\n"), entry_offset, entry_offset);
428 fprintf (f, _("Length = 0x%.8lx (%ld)\n"), length, length);
429
430 if (tdata->header.flags)
431 fprintf (f, _("Flag field = 0x%.2x\n"), tdata->header.flags);
432
433 if (tdata->header.os_id)
434 fprintf (f, "OS_ID = 0x%.2x\n", tdata->header.os_id);
435
436 if (tdata->header.partition_name)
437 fprintf (f, _("Partition name = \"%s\"\n"), tdata->header.partition_name);
438
439 for (i = 0; i < 4; i++)
440 {
441 long sector_begin = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_begin);
442 long sector_length = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_length);
443
444 /* Skip all 0 entries */
445 if (!tdata->header.partition[i].partition_begin.ind
446 && !tdata->header.partition[i].partition_begin.head
447 && !tdata->header.partition[i].partition_begin.sector
448 && !tdata->header.partition[i].partition_begin.cylinder
449 && !tdata->header.partition[i].partition_end.ind
450 && !tdata->header.partition[i].partition_end.head
451 && !tdata->header.partition[i].partition_end.sector
452 && !tdata->header.partition[i].partition_end.cylinder
453 && !sector_begin && !sector_length)
454 continue;
455
456 fprintf (f, _("\nPartition[%d] start = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
457 tdata->header.partition[i].partition_begin.ind,
458 tdata->header.partition[i].partition_begin.head,
459 tdata->header.partition[i].partition_begin.sector,
460 tdata->header.partition[i].partition_begin.cylinder);
461
462 fprintf (f, _("Partition[%d] end = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
463 tdata->header.partition[i].partition_end.ind,
464 tdata->header.partition[i].partition_end.head,
465 tdata->header.partition[i].partition_end.sector,
466 tdata->header.partition[i].partition_end.cylinder);
467
468 fprintf (f, _("Partition[%d] sector = 0x%.8lx (%ld)\n"), i, sector_begin, sector_begin);
469 fprintf (f, _("Partition[%d] length = 0x%.8lx (%ld)\n"), i, sector_length, sector_length);
470 }
471
472 fprintf (f, "\n");
473 return TRUE;
474}
475
476
477
478#define ppcboot_bfd_get_relocated_section_contents \
479 bfd_generic_get_relocated_section_contents
480#define ppcboot_bfd_relax_section bfd_generic_relax_section
481#define ppcboot_bfd_gc_sections bfd_generic_gc_sections
482#define ppcboot_bfd_merge_sections bfd_generic_merge_sections
483#define ppcboot_bfd_discard_group bfd_generic_discard_group
484#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
485#define ppcboot_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
486#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
487#define ppcboot_bfd_link_just_syms _bfd_generic_link_just_syms
488#define ppcboot_bfd_final_link _bfd_generic_final_link
489#define ppcboot_bfd_link_split_section _bfd_generic_link_split_section
490#define ppcboot_get_section_contents_in_window \
491 _bfd_generic_get_section_contents_in_window
492
493#define ppcboot_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
494#define ppcboot_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
495#define ppcboot_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
496#define ppcboot_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
497#define ppcboot_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
498#define ppcboot_bfd_print_private_bfd_dat ppcboot_bfd_print_private_bfd_data
499
500const bfd_target ppcboot_vec =
501{
502 "ppcboot", /* name */
503 bfd_target_unknown_flavour, /* flavour */
504 BFD_ENDIAN_BIG, /* byteorder is big endian for code */
505 BFD_ENDIAN_LITTLE, /* header_byteorder */
506 EXEC_P, /* object_flags */
507 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
508 | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
509 0, /* symbol_leading_char */
510 ' ', /* ar_pad_char */
511 16, /* ar_max_namelen */
512 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
513 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
514 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
515 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
516 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
517 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
518 { /* bfd_check_format */
519 _bfd_dummy_target,
520 ppcboot_object_p, /* bfd_check_format */
521 _bfd_dummy_target,
522 _bfd_dummy_target,
523 },
524 { /* bfd_set_format */
525 bfd_false,
526 ppcboot_mkobject,
527 bfd_false,
528 bfd_false,
529 },
530 { /* bfd_write_contents */
531 bfd_false,
532 bfd_true,
533 bfd_false,
534 bfd_false,
535 },
536
537 BFD_JUMP_TABLE_GENERIC (ppcboot),
538 BFD_JUMP_TABLE_COPY (ppcboot),
539 BFD_JUMP_TABLE_CORE (_bfd_nocore),
540 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
541 BFD_JUMP_TABLE_SYMBOLS (ppcboot),
542 BFD_JUMP_TABLE_RELOCS (ppcboot),
543 BFD_JUMP_TABLE_WRITE (ppcboot),
544 BFD_JUMP_TABLE_LINK (ppcboot),
545 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
546
547 NULL,
548
549 NULL
550};
Note: See TracBrowser for help on using the repository browser.