00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "safe-ctype.h"
00040 #include "bfd.h"
00041 #include "sysdep.h"
00042 #include "libbfd.h"
00043
00044
00045 typedef struct ppcboot_location {
00046 bfd_byte ind;
00047 bfd_byte head;
00048 bfd_byte sector;
00049 bfd_byte cylinder;
00050 } ppcboot_location_t;
00051
00052
00053 typedef struct ppcboot_partition {
00054 ppcboot_location_t partition_begin;
00055 ppcboot_location_t partition_end;
00056 bfd_byte sector_begin[4];
00057 bfd_byte sector_length[4];
00058 } ppcboot_partition_t;
00059
00060
00061 typedef struct ppcboot_hdr {
00062 bfd_byte pc_compatibility[446];
00063 ppcboot_partition_t partition[4];
00064 bfd_byte signature[2];
00065 bfd_byte entry_offset[4];
00066 bfd_byte length[4];
00067 bfd_byte flags;
00068 bfd_byte os_id;
00069 char partition_name[32];
00070 bfd_byte reserved1[470];
00071 }
00072 #ifdef __GNUC__
00073 __attribute__ ((packed))
00074 #endif
00075 ppcboot_hdr_t;
00076
00077
00078 #define SIGNATURE0 0x55
00079 #define SIGNATURE1 0xaa
00080
00081
00082 #define PPC_IND 0x41
00083
00084
00085 typedef struct ppcboot_data {
00086 ppcboot_hdr_t header;
00087 asection *sec;
00088 } ppcboot_data_t;
00089
00090
00091
00092 #define PPCBOOT_SYMS 3
00093
00094 static bfd_boolean ppcboot_mkobject PARAMS ((bfd *));
00095 static const bfd_target *ppcboot_object_p PARAMS ((bfd *));
00096 static bfd_boolean ppcboot_set_arch_mach
00097 PARAMS ((bfd *, enum bfd_architecture, unsigned long));
00098 static bfd_boolean ppcboot_get_section_contents
00099 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
00100 static long ppcboot_get_symtab_upper_bound PARAMS ((bfd *));
00101 static char *mangle_name PARAMS ((bfd *, char *));
00102 static long ppcboot_canonicalize_symtab PARAMS ((bfd *, asymbol **));
00103 static void ppcboot_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
00104 static bfd_boolean ppcboot_set_section_contents
00105 PARAMS ((bfd *, asection *, const PTR, file_ptr, bfd_size_type));
00106 static int ppcboot_sizeof_headers PARAMS ((bfd *, bfd_boolean));
00107 static bfd_boolean ppcboot_bfd_print_private_bfd_data PARAMS ((bfd *, PTR));
00108
00109 #define ppcboot_set_tdata(abfd, ptr) ((abfd)->tdata.any = (PTR) (ptr))
00110 #define ppcboot_get_tdata(abfd) ((ppcboot_data_t *) ((abfd)->tdata.any))
00111
00112
00113
00114 static bfd_boolean
00115 ppcboot_mkobject (abfd)
00116 bfd *abfd;
00117 {
00118 if (!ppcboot_get_tdata (abfd))
00119 {
00120 bfd_size_type amt = sizeof (ppcboot_data_t);
00121 ppcboot_set_tdata (abfd, bfd_zalloc (abfd, amt));
00122 }
00123
00124 return TRUE;
00125 }
00126
00127
00128
00129 static bfd_boolean
00130 ppcboot_set_arch_mach (abfd, arch, machine)
00131 bfd *abfd;
00132 enum bfd_architecture arch;
00133 unsigned long machine;
00134 {
00135 if (arch == bfd_arch_unknown)
00136 arch = bfd_arch_powerpc;
00137
00138 else if (arch != bfd_arch_powerpc)
00139 return FALSE;
00140
00141 return bfd_default_set_arch_mach (abfd, arch, machine);
00142 }
00143
00144
00145
00146
00147
00148
00149 static const bfd_target *
00150 ppcboot_object_p (abfd)
00151 bfd *abfd;
00152 {
00153 struct stat statbuf;
00154 asection *sec;
00155 ppcboot_hdr_t hdr;
00156 size_t i;
00157 ppcboot_data_t *tdata;
00158
00159 BFD_ASSERT (sizeof (ppcboot_hdr_t) == 1024);
00160
00161 if (abfd->target_defaulted)
00162 {
00163 bfd_set_error (bfd_error_wrong_format);
00164 return NULL;
00165 }
00166
00167
00168 if (bfd_stat (abfd, &statbuf) < 0)
00169 {
00170 bfd_set_error (bfd_error_system_call);
00171 return NULL;
00172 }
00173
00174 if ((size_t) statbuf.st_size < sizeof (ppcboot_hdr_t))
00175 {
00176 bfd_set_error (bfd_error_wrong_format);
00177 return NULL;
00178 }
00179
00180 if (bfd_bread ((PTR) &hdr, (bfd_size_type) sizeof (hdr), abfd)
00181 != sizeof (hdr))
00182 {
00183 if (bfd_get_error () != bfd_error_system_call)
00184 bfd_set_error (bfd_error_wrong_format);
00185
00186 return NULL;
00187 }
00188
00189
00190 for (i = 0; i < sizeof (hdr.pc_compatibility); i++)
00191 if (hdr.pc_compatibility[i])
00192 {
00193 bfd_set_error (bfd_error_wrong_format);
00194 return NULL;
00195 }
00196
00197 if (hdr.signature[0] != SIGNATURE0 || hdr.signature[1] != SIGNATURE1)
00198 {
00199 bfd_set_error (bfd_error_wrong_format);
00200 return NULL;
00201 }
00202
00203 if (hdr.partition[0].partition_end.ind != PPC_IND)
00204 {
00205 bfd_set_error (bfd_error_wrong_format);
00206 return NULL;
00207 }
00208
00209 abfd->symcount = PPCBOOT_SYMS;
00210
00211
00212 sec = bfd_make_section (abfd, ".data");
00213 if (sec == NULL)
00214 return NULL;
00215 sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_CODE | SEC_HAS_CONTENTS;
00216 sec->vma = 0;
00217 sec->size = statbuf.st_size - sizeof (ppcboot_hdr_t);
00218 sec->filepos = sizeof (ppcboot_hdr_t);
00219
00220 ppcboot_mkobject (abfd);
00221 tdata = ppcboot_get_tdata (abfd);
00222 tdata->sec = sec;
00223 memcpy ((PTR) &tdata->header, (PTR) &hdr, sizeof (ppcboot_hdr_t));
00224
00225 ppcboot_set_arch_mach (abfd, bfd_arch_powerpc, 0L);
00226 return abfd->xvec;
00227 }
00228
00229 #define ppcboot_close_and_cleanup _bfd_generic_close_and_cleanup
00230 #define ppcboot_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
00231 #define ppcboot_new_section_hook _bfd_generic_new_section_hook
00232
00233
00234
00235
00236 static bfd_boolean
00237 ppcboot_get_section_contents (abfd, section, location, offset, count)
00238 bfd *abfd;
00239 asection *section ATTRIBUTE_UNUSED;
00240 PTR location;
00241 file_ptr offset;
00242 bfd_size_type count;
00243 {
00244 if (bfd_seek (abfd, offset + (file_ptr) sizeof (ppcboot_hdr_t), SEEK_SET) != 0
00245 || bfd_bread (location, count, abfd) != count)
00246 return FALSE;
00247 return TRUE;
00248 }
00249
00250
00251
00252
00253 static long
00254 ppcboot_get_symtab_upper_bound (abfd)
00255 bfd *abfd ATTRIBUTE_UNUSED;
00256 {
00257 return (PPCBOOT_SYMS + 1) * sizeof (asymbol *);
00258 }
00259
00260
00261
00262
00263 static char *
00264 mangle_name (abfd, suffix)
00265 bfd *abfd;
00266 char *suffix;
00267 {
00268 bfd_size_type size;
00269 char *buf;
00270 char *p;
00271
00272 size = (strlen (bfd_get_filename (abfd))
00273 + strlen (suffix)
00274 + sizeof "_ppcboot__");
00275
00276 buf = (char *) bfd_alloc (abfd, size);
00277 if (buf == NULL)
00278 return "";
00279
00280 sprintf (buf, "_ppcboot_%s_%s", bfd_get_filename (abfd), suffix);
00281
00282
00283 for (p = buf; *p; p++)
00284 if (! ISALNUM (*p))
00285 *p = '_';
00286
00287 return buf;
00288 }
00289
00290
00291
00292
00293 static long
00294 ppcboot_canonicalize_symtab (abfd, alocation)
00295 bfd *abfd;
00296 asymbol **alocation;
00297 {
00298 asection *sec = ppcboot_get_tdata (abfd)->sec;
00299 asymbol *syms;
00300 unsigned int i;
00301 bfd_size_type amt = PPCBOOT_SYMS * sizeof (asymbol);
00302
00303 syms = (asymbol *) bfd_alloc (abfd, amt);
00304 if (syms == NULL)
00305 return FALSE;
00306
00307
00308 syms[0].the_bfd = abfd;
00309 syms[0].name = mangle_name (abfd, "start");
00310 syms[0].value = 0;
00311 syms[0].flags = BSF_GLOBAL;
00312 syms[0].section = sec;
00313 syms[0].udata.p = NULL;
00314
00315
00316 syms[1].the_bfd = abfd;
00317 syms[1].name = mangle_name (abfd, "end");
00318 syms[1].value = sec->size;
00319 syms[1].flags = BSF_GLOBAL;
00320 syms[1].section = sec;
00321 syms[1].udata.p = NULL;
00322
00323
00324 syms[2].the_bfd = abfd;
00325 syms[2].name = mangle_name (abfd, "size");
00326 syms[2].value = sec->size;
00327 syms[2].flags = BSF_GLOBAL;
00328 syms[2].section = bfd_abs_section_ptr;
00329 syms[2].udata.p = NULL;
00330
00331 for (i = 0; i < PPCBOOT_SYMS; i++)
00332 *alocation++ = syms++;
00333 *alocation = NULL;
00334
00335 return PPCBOOT_SYMS;
00336 }
00337
00338 #define ppcboot_make_empty_symbol _bfd_generic_make_empty_symbol
00339 #define ppcboot_print_symbol _bfd_nosymbols_print_symbol
00340
00341
00342
00343 static void
00344 ppcboot_get_symbol_info (ignore_abfd, symbol, ret)
00345 bfd *ignore_abfd ATTRIBUTE_UNUSED;
00346 asymbol *symbol;
00347 symbol_info *ret;
00348 {
00349 bfd_symbol_info (symbol, ret);
00350 }
00351
00352 #define ppcboot_bfd_is_target_special_symbol \
00353 ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
00354 #define ppcboot_bfd_is_local_label_name bfd_generic_is_local_label_name
00355 #define ppcboot_get_lineno _bfd_nosymbols_get_lineno
00356 #define ppcboot_find_nearest_line _bfd_nosymbols_find_nearest_line
00357 #define ppcboot_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
00358 #define ppcboot_read_minisymbols _bfd_generic_read_minisymbols
00359 #define ppcboot_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
00360
00361 #define ppcboot_get_reloc_upper_bound \
00362 ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
00363 #define ppcboot_canonicalize_reloc \
00364 ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
00365 #define ppcboot_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
00366
00367
00368
00369 static bfd_boolean
00370 ppcboot_set_section_contents (abfd, sec, data, offset, size)
00371 bfd *abfd;
00372 asection *sec;
00373 const PTR data;
00374 file_ptr offset;
00375 bfd_size_type size;
00376 {
00377 if (! abfd->output_has_begun)
00378 {
00379 bfd_vma low;
00380 asection *s;
00381
00382
00383
00384
00385 low = abfd->sections->vma;
00386 for (s = abfd->sections->next; s != NULL; s = s->next)
00387 if (s->vma < low)
00388 low = s->vma;
00389
00390 for (s = abfd->sections; s != NULL; s = s->next)
00391 s->filepos = s->vma - low;
00392
00393 abfd->output_has_begun = TRUE;
00394 }
00395
00396 return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
00397 }
00398
00399
00400 static int
00401 ppcboot_sizeof_headers (abfd, exec)
00402 bfd *abfd ATTRIBUTE_UNUSED;
00403 bfd_boolean exec ATTRIBUTE_UNUSED;
00404 {
00405 return sizeof (ppcboot_hdr_t);
00406 }
00407
00408
00409
00410
00411 static bfd_boolean
00412 ppcboot_bfd_print_private_bfd_data (abfd, farg)
00413 bfd *abfd;
00414 PTR farg;
00415 {
00416 FILE *f = (FILE *)farg;
00417 ppcboot_data_t *tdata = ppcboot_get_tdata (abfd);
00418 long entry_offset = bfd_getl_signed_32 ((PTR) tdata->header.entry_offset);
00419 long length = bfd_getl_signed_32 ((PTR) tdata->header.length);
00420 int i;
00421
00422 fprintf (f, _("\nppcboot header:\n"));
00423 fprintf (f, _("Entry offset = 0x%.8lx (%ld)\n"), entry_offset, entry_offset);
00424 fprintf (f, _("Length = 0x%.8lx (%ld)\n"), length, length);
00425
00426 if (tdata->header.flags)
00427 fprintf (f, _("Flag field = 0x%.2x\n"), tdata->header.flags);
00428
00429 if (tdata->header.os_id)
00430 fprintf (f, "OS_ID = 0x%.2x\n", tdata->header.os_id);
00431
00432 if (tdata->header.partition_name)
00433 fprintf (f, _("Partition name = \"%s\"\n"), tdata->header.partition_name);
00434
00435 for (i = 0; i < 4; i++)
00436 {
00437 long sector_begin = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_begin);
00438 long sector_length = bfd_getl_signed_32 ((PTR) tdata->header.partition[i].sector_length);
00439
00440
00441 if (!tdata->header.partition[i].partition_begin.ind
00442 && !tdata->header.partition[i].partition_begin.head
00443 && !tdata->header.partition[i].partition_begin.sector
00444 && !tdata->header.partition[i].partition_begin.cylinder
00445 && !tdata->header.partition[i].partition_end.ind
00446 && !tdata->header.partition[i].partition_end.head
00447 && !tdata->header.partition[i].partition_end.sector
00448 && !tdata->header.partition[i].partition_end.cylinder
00449 && !sector_begin && !sector_length)
00450 continue;
00451
00452 fprintf (f, _("\nPartition[%d] start = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
00453 tdata->header.partition[i].partition_begin.ind,
00454 tdata->header.partition[i].partition_begin.head,
00455 tdata->header.partition[i].partition_begin.sector,
00456 tdata->header.partition[i].partition_begin.cylinder);
00457
00458 fprintf (f, _("Partition[%d] end = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"), i,
00459 tdata->header.partition[i].partition_end.ind,
00460 tdata->header.partition[i].partition_end.head,
00461 tdata->header.partition[i].partition_end.sector,
00462 tdata->header.partition[i].partition_end.cylinder);
00463
00464 fprintf (f, _("Partition[%d] sector = 0x%.8lx (%ld)\n"), i, sector_begin, sector_begin);
00465 fprintf (f, _("Partition[%d] length = 0x%.8lx (%ld)\n"), i, sector_length, sector_length);
00466 }
00467
00468 fprintf (f, "\n");
00469 return TRUE;
00470 }
00471
00472
00473 #define ppcboot_bfd_get_relocated_section_contents \
00474 bfd_generic_get_relocated_section_contents
00475 #define ppcboot_bfd_relax_section bfd_generic_relax_section
00476 #define ppcboot_bfd_gc_sections bfd_generic_gc_sections
00477 #define ppcboot_bfd_merge_sections bfd_generic_merge_sections
00478 #define ppcboot_bfd_is_group_section bfd_generic_is_group_section
00479 #define ppcboot_bfd_discard_group bfd_generic_discard_group
00480 #define ppcboot_section_already_linked \
00481 _bfd_generic_section_already_linked
00482 #define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
00483 #define ppcboot_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
00484 #define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
00485 #define ppcboot_bfd_link_just_syms _bfd_generic_link_just_syms
00486 #define ppcboot_bfd_final_link _bfd_generic_final_link
00487 #define ppcboot_bfd_link_split_section _bfd_generic_link_split_section
00488 #define ppcboot_get_section_contents_in_window \
00489 _bfd_generic_get_section_contents_in_window
00490
00491 #define ppcboot_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
00492 #define ppcboot_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
00493 #define ppcboot_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
00494 #define ppcboot_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
00495 #define ppcboot_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
00496 #define ppcboot_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
00497 #define ppcboot_bfd_print_private_bfd_dat ppcboot_bfd_print_private_bfd_data
00498
00499 const bfd_target ppcboot_vec =
00500 {
00501 "ppcboot",
00502 bfd_target_unknown_flavour,
00503 BFD_ENDIAN_BIG,
00504 BFD_ENDIAN_LITTLE,
00505 EXEC_P,
00506 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
00507 | SEC_ROM | SEC_HAS_CONTENTS),
00508 0,
00509 ' ',
00510 16,
00511 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00512 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00513 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00514 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00515 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00516 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00517 {
00518 _bfd_dummy_target,
00519 ppcboot_object_p,
00520 _bfd_dummy_target,
00521 _bfd_dummy_target,
00522 },
00523 {
00524 bfd_false,
00525 ppcboot_mkobject,
00526 bfd_false,
00527 bfd_false,
00528 },
00529 {
00530 bfd_false,
00531 bfd_true,
00532 bfd_false,
00533 bfd_false,
00534 },
00535
00536 BFD_JUMP_TABLE_GENERIC (ppcboot),
00537 BFD_JUMP_TABLE_COPY (ppcboot),
00538 BFD_JUMP_TABLE_CORE (_bfd_nocore),
00539 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00540 BFD_JUMP_TABLE_SYMBOLS (ppcboot),
00541 BFD_JUMP_TABLE_RELOCS (ppcboot),
00542 BFD_JUMP_TABLE_WRITE (ppcboot),
00543 BFD_JUMP_TABLE_LINK (ppcboot),
00544 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00545
00546 NULL,
00547
00548 NULL
00549 };