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