Add PPCbug boot record support
authorMichael Meissner <gnu@the-meissners.org>
Tue, 7 May 1996 20:20:55 +0000 (20:20 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Tue, 7 May 1996 20:20:55 +0000 (20:20 +0000)
bfd/.Sanitize
bfd/ChangeLog
bfd/ppcboot.c [new file with mode: 0644]

index 54fca53f1380535e1bc836b12920b2009e7ddf1d..4e9e373e86c900a671adbbb0ed727ba413ebf8de 100644 (file)
@@ -229,6 +229,7 @@ pei-arm.c
 pei-i386.c
 pei-ppc.c
 peicode.h
+ppcboot.c
 ptrace-core.c
 reloc.c
 reloc16.c
index f64c3f3e17a7582a4b5e12d90551d594f12f0744..b6f5b6f066920e51eb11cb9bd77140ee61c14b44 100644 (file)
@@ -1,3 +1,11 @@
+Tue May  7 16:10:19 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * ppcboot.c: New target for looking at PPCbug boot records.
+
+       * config{ure.in,.bfd}: Add support for ppcboot target.
+       * targets.c: Ditto.
+       * configure: Regenerate.
+               
 Tue May  7 11:15:19 1996  Jeffrey A Law  (law@cygnus.com)
 
        * coff-h8300.c (howto_table): Update names to match recent
diff --git a/bfd/ppcboot.c b/bfd/ppcboot.c
new file mode 100644 (file)
index 0000000..40b8c19
--- /dev/null
@@ -0,0 +1,527 @@
+/* BFD back-end for PPCbug boot records.
+   Copyright 1996 Free Software Foundation, Inc.
+   Written by Michael Meissner, Cygnus Support, <meissner@cygnus.com>
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* This is a BFD backend which may be used to write PowerPCBug boot objects.
+   It may only be used for output, not input.  The intention is that this may
+   be used as an output format for objcopy in order to generate raw binary
+   data.
+
+   This is very simple.  The only complication is that the real data
+   will start at some address X, and in some cases we will not want to
+   include X zeroes just to get to that point.  Since the start
+   address is not meaningful for this object file format, we use it
+   instead to indicate the number of zeroes to skip at the start of
+   the file.  objcopy cooperates by specially setting the start
+   address to zero by default.  */
+
+#include <ctype.h>
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* PPCbug location structure */
+typedef struct ppcboot_location {
+  bfd_byte     ind;
+  bfd_byte     head;
+  bfd_byte     sector;
+  bfd_byte     cylinder;
+} ppcboot_location_t;
+
+/* PPCbug partition table layout */
+typedef struct ppcboot_partition {
+  ppcboot_location_t   partition_begin;        /* partition begin */
+  ppcboot_location_t   partition_end;          /* partition end */
+  bfd_byte             sector_begin[4];        /* 32-bit start RBA (zero-based), little endian */
+  bfd_byte             sector_length[4];       /* 32-bit RBA count (one-based), little endian */
+} ppcboot_partition_t;
+
+/* PPCbug boot layout.  */
+typedef struct ppcboot_hdr {
+  bfd_byte             pc_compatibility[446];  /* x86 instruction field */
+  ppcboot_partition_t  partition[4];           /* partition information */
+  bfd_byte             signature[2];           /* 0x55 and 0xaa */
+  bfd_byte             entry_offset[4];        /* entry point offset, little endian */
+  bfd_byte             length[4];              /* load image length, little endian */
+  bfd_byte             flags;                  /* flag field */
+  bfd_byte             os_id;                  /* OS_ID */
+  char                 partition_name[32];     /* partition name */
+  bfd_byte             reserved1[470];         /* reserved */
+} ppcboot_hdr_t;
+
+/* Signature bytes for last 2 bytes of the 512 byte record */
+#define SIGNATURE0 0x55
+#define SIGNATURE1 0xaa
+
+/* Information needed for ppcboot header */
+typedef struct ppcboot_data {
+  ppcboot_hdr_t        header;                         /* raw header */
+  asection *sec;                               /* single section */
+} ppcboot_data_t;
+
+/* Any bfd we create by reading a ppcboot file has three symbols:
+   a start symbol, an end symbol, and an absolute length symbol.  */
+#define PPCBOOT_SYMS 3
+
+static boolean ppcboot_mkobject PARAMS ((bfd *));
+static const bfd_target *ppcboot_object_p PARAMS ((bfd *));
+static boolean ppcboot_get_section_contents
+  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static long ppcboot_get_symtab_upper_bound PARAMS ((bfd *));
+static char *mangle_name PARAMS ((bfd *, char *));
+static long ppcboot_get_symtab PARAMS ((bfd *, asymbol **));
+static asymbol *ppcboot_make_empty_symbol PARAMS ((bfd *));
+static void ppcboot_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static boolean ppcboot_set_section_contents
+  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static int ppcboot_sizeof_headers PARAMS ((bfd *, boolean));
+
+#define ppcboot_set_tdata(abfd, ptr) ((abfd)->tdata.any = (PTR) (ptr))
+#define ppcboot_get_tdata(abfd) ((ppcboot_data_t *) ((abfd)->tdata.any))
+\f
+/* Create a ppcboot object.  Invoked via bfd_set_format.  */
+
+static boolean
+ppcboot_mkobject (abfd)
+     bfd *abfd;
+{
+  if (!ppcboot_get_tdata (abfd))
+    ppcboot_set_tdata (abfd, bfd_zalloc (abfd, sizeof (ppcboot_data_t)));
+
+  return true;
+}
+
+\f
+/* Set the architecture to PowerPC */
+boolean
+ppcboot_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  if (arch == bfd_arch_unknown)
+    arch = bfd_arch_powerpc;
+
+  else if (arch != bfd_arch_powerpc)
+    return false;
+
+  return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+\f
+/* Any file may be considered to be a ppcboot file, provided the target
+   was not defaulted.  That is, it must be explicitly specified as
+   being ppcboot.  */
+
+static const bfd_target *
+ppcboot_object_p (abfd)
+     bfd *abfd;
+{
+  struct stat statbuf;
+  asection *sec;
+  ppcboot_hdr_t hdr;
+  int i;
+  ppcboot_data_t *tdata;
+
+  if (sizeof (ppcboot_hdr_t) != 1024)
+    fatal ("ppcboot_hdr_t is not 1024 bytes in size");
+
+  if (abfd->target_defaulted)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  abfd->symcount = PPCBOOT_SYMS;
+
+  /* Find the file size.  */
+  if (bfd_stat (abfd, &statbuf) < 0)
+    {
+      bfd_set_error (bfd_error_system_call);
+      return NULL;
+    }
+
+  if (statbuf.st_size < sizeof (ppcboot_hdr_t))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (bfd_read ((PTR) &hdr, sizeof (hdr), 1, abfd) != sizeof (hdr))
+    {
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
+
+      return NULL;
+    }
+
+  /* Now do some basic checks.  */
+  for (i = 0; i < sizeof (hdr.pc_compatibility); i++)
+    if (hdr.pc_compatibility[i])
+      {
+       bfd_set_error (bfd_error_wrong_format);
+       return NULL;
+      }
+
+  if (hdr.signature[0] != SIGNATURE0 || hdr.signature[1] != SIGNATURE1)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  /* One data section.  */
+  sec = bfd_make_section (abfd, ".data");
+  if (sec == NULL)
+    return NULL;
+  sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_CODE | SEC_HAS_CONTENTS;
+  sec->vma = 0;
+  sec->_raw_size = statbuf.st_size - sizeof (ppcboot_hdr_t);
+  sec->filepos = sizeof (ppcboot_hdr_t);
+
+  ppcboot_mkobject (abfd);
+  tdata = ppcboot_get_tdata (abfd);
+  tdata->sec = sec;
+  memcpy ((PTR) &tdata->header, (PTR) &hdr, sizeof (ppcboot_hdr_t));
+
+  ppcboot_set_arch_mach (abfd, bfd_arch_powerpc, 0);
+  return abfd->xvec;
+}
+
+#define ppcboot_close_and_cleanup _bfd_generic_close_and_cleanup
+#define ppcboot_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define ppcboot_new_section_hook _bfd_generic_new_section_hook
+
+\f
+/* Get contents of the only section.  */
+
+static boolean
+ppcboot_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     asection *section;
+     PTR location;
+     file_ptr offset;
+     bfd_size_type count;
+{
+  if (bfd_seek (abfd, offset + sizeof(ppcboot_hdr_t), SEEK_SET) != 0
+      || bfd_read (location, 1, count, abfd) != count)
+    return false;
+  return true;
+}
+
+\f
+/* Return the amount of memory needed to read the symbol table.  */
+
+static long
+ppcboot_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  return (PPCBOOT_SYMS + 1) * sizeof (asymbol *);
+}
+
+\f
+/* Create a symbol name based on the bfd's filename.  */
+
+static char *
+mangle_name (abfd, suffix)
+     bfd *abfd;
+     char *suffix;
+{
+  int size;
+  char *buf;
+  char *p;
+
+  size = (strlen (bfd_get_filename (abfd))
+         + strlen (suffix)
+         + sizeof "_ppcboot__");
+
+  buf = (char *) bfd_alloc (abfd, size);
+  if (buf == NULL)
+    return "";
+
+  sprintf (buf, "_ppcboot_%s_%s", bfd_get_filename (abfd), suffix);
+
+  /* Change any non-alphanumeric characters to underscores.  */
+  for (p = buf; *p; p++)
+    if (! isalnum (*p))
+      *p = '_';
+
+  return buf;
+}
+
+\f
+/* Return the symbol table.  */
+
+static long
+ppcboot_get_symtab (abfd, alocation)
+     bfd *abfd;
+     asymbol **alocation;
+{
+  asection *sec = ppcboot_get_tdata (abfd)->sec;
+  asymbol *syms;
+  unsigned int i;
+
+  syms = (asymbol *) bfd_alloc (abfd, PPCBOOT_SYMS * sizeof (asymbol));
+  if (syms == NULL)
+    return false;
+
+  /* Start symbol.  */
+  syms[0].the_bfd = abfd;
+  syms[0].name = mangle_name (abfd, "start");
+  syms[0].value = 0;
+  syms[0].flags = BSF_GLOBAL;
+  syms[0].section = sec;
+  syms[0].udata.p = NULL;
+
+  /* End symbol.  */
+  syms[1].the_bfd = abfd;
+  syms[1].name = mangle_name (abfd, "end");
+  syms[1].value = sec->_raw_size;
+  syms[1].flags = BSF_GLOBAL;
+  syms[1].section = sec;
+  syms[1].udata.p = NULL;
+
+  /* Size symbol.  */
+  syms[2].the_bfd = abfd;
+  syms[2].name = mangle_name (abfd, "size");
+  syms[2].value = sec->_raw_size;
+  syms[2].flags = BSF_GLOBAL;
+  syms[2].section = bfd_abs_section_ptr;
+  syms[2].udata.p = NULL;
+
+  for (i = 0; i < PPCBOOT_SYMS; i++)
+    *alocation++ = syms++;
+  *alocation = NULL;
+
+  return PPCBOOT_SYMS;
+}
+
+\f
+/* Make an empty symbol.  */
+
+static asymbol *
+ppcboot_make_empty_symbol (abfd)
+     bfd *abfd;
+{
+  return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
+}
+
+\f
+#define ppcboot_print_symbol _bfd_nosymbols_print_symbol
+
+/* Get information about a symbol.  */
+
+static void
+ppcboot_get_symbol_info (ignore_abfd, symbol, ret)
+     bfd *ignore_abfd;
+     asymbol *symbol;
+     symbol_info *ret;
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+#define ppcboot_bfd_is_local_label bfd_generic_is_local_label
+#define ppcboot_get_lineno _bfd_nosymbols_get_lineno
+#define ppcboot_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define ppcboot_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define ppcboot_read_minisymbols _bfd_generic_read_minisymbols
+#define ppcboot_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define ppcboot_get_reloc_upper_bound \
+  ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define ppcboot_canonicalize_reloc \
+  ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define ppcboot_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+/* Set the architecture of a ppcboot file.  */
+#define ppcboot_set_arch_mach ppcboot_set_arch_mach
+
+\f
+/* Write section contents of a ppcboot file.  */
+
+static boolean
+ppcboot_set_section_contents (abfd, sec, data, offset, size)
+     bfd *abfd;
+     asection *sec;
+     PTR data;
+     file_ptr offset;
+     bfd_size_type size;
+{
+  if (! abfd->output_has_begun)
+    {
+      bfd_vma low;
+      asection *s;
+
+      /* The lowest section VMA sets the virtual address of the start
+         of the file.  We use the set the file position of all the
+         sections.  */
+      low = abfd->sections->vma;
+      for (s = abfd->sections->next; s != NULL; s = s->next)
+       if (s->vma < low)
+         low = s->vma;
+
+      for (s = abfd->sections; s != NULL; s = s->next)
+       s->filepos = s->vma - low;
+
+      abfd->output_has_begun = true;
+    }
+
+  return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
+}
+
+\f
+static int
+ppcboot_sizeof_headers (abfd, exec)
+     bfd *abfd;
+     boolean exec;
+{
+  return sizeof (ppcboot_hdr_t);
+}
+
+\f
+/* Print out the program headers.  */
+
+boolean
+ppcboot_bfd_print_private_bfd_data (abfd, farg)
+     bfd *abfd;
+     PTR farg;
+{
+  FILE *f = (FILE *)farg;
+  ppcboot_data_t *tdata = ppcboot_get_tdata (abfd);
+  long entry_offset = bfd_getl_signed_32 ((PTR) &tdata->header.entry_offset);
+  long length = bfd_getl_signed_32 ((PTR) &tdata->header.length);
+  int i;
+
+  fprintf (f, "\nppcboot header:\n");
+  fprintf (f, "Entry offset        = 0x%.8lx (%ld)\n", entry_offset, entry_offset);
+  fprintf (f, "Length              = 0x%.8lx (%ld)\n", length, length);
+
+  if (tdata->header.flags)
+    fprintf (f, "Flag field          = 0x%.2x\n", tdata->header.flags);
+
+  if (tdata->header.os_id)
+    fprintf (f, "OS_ID               = 0x%.2x\n", tdata->header.os_id);
+
+  if (tdata->header.partition_name)
+    fprintf (f, "Partition name      = %s\n", tdata->header.partition_name);
+
+  for (i = 0; i < 4; i++)
+    {
+      long sector_begin  = bfd_getl_signed_32 ((PTR) &tdata->header.partition[i].sector_begin);
+      long sector_length = bfd_getl_signed_32 ((PTR) &tdata->header.partition[i].sector_length);
+
+      /* Skip all 0 entries */
+      if (!tdata->header.partition[i].partition_begin.ind
+         && !tdata->header.partition[i].partition_begin.head
+         && !tdata->header.partition[i].partition_begin.sector
+         && !tdata->header.partition[i].partition_begin.cylinder
+         && !tdata->header.partition[i].partition_end.ind
+         && !tdata->header.partition[i].partition_end.head
+         && !tdata->header.partition[i].partition_end.sector
+         && !tdata->header.partition[i].partition_end.cylinder
+         && !sector_begin && !sector_length)
+       continue;
+
+      fprintf (f, "\nPartition[%d] start  = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n", i,
+              tdata->header.partition[i].partition_begin.ind,
+              tdata->header.partition[i].partition_begin.head,
+              tdata->header.partition[i].partition_begin.sector,
+              tdata->header.partition[i].partition_begin.cylinder);
+
+      fprintf (f, "Partition[%d] end    = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n", i,
+              tdata->header.partition[i].partition_end.ind,
+              tdata->header.partition[i].partition_end.head,
+              tdata->header.partition[i].partition_end.sector,
+              tdata->header.partition[i].partition_end.cylinder);
+
+      fprintf (f, "Partition[%d] sector = 0x%.8lx (%ld)\n", i, sector_begin, sector_begin);
+      fprintf (f, "Partition[%d] length = 0x%.8lx (%ld)\n", i, sector_length, sector_length);
+    }
+
+  fprintf (f, "\n");
+  return true;
+}
+
+\f
+#define ppcboot_bfd_get_relocated_section_contents \
+  bfd_generic_get_relocated_section_contents
+#define ppcboot_bfd_relax_section bfd_generic_relax_section
+#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define ppcboot_bfd_final_link _bfd_generic_final_link
+#define ppcboot_bfd_link_split_section _bfd_generic_link_split_section
+#define ppcboot_get_section_contents_in_window \
+  _bfd_generic_get_section_contents_in_window
+
+#define ppcboot_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
+#define ppcboot_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define ppcboot_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
+#define ppcboot_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
+#define ppcboot_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#define ppcboot_bfd_print_private_bfd_dat ppcboot_bfd_print_private_bfd_data
+
+const bfd_target ppcboot_vec =
+{
+  "ppcboot",                   /* name */
+  bfd_target_unknown_flavour,  /* flavour */
+  BFD_ENDIAN_BIG,              /* byteorder is big endian for code */
+  BFD_ENDIAN_LITTLE,           /* header_byteorder */
+  EXEC_P,                      /* object_flags */
+  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+  0,                           /* symbol_leading_char */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* data */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* hdrs */
+  {                            /* bfd_check_format */
+    _bfd_dummy_target,
+    ppcboot_object_p,          /* bfd_check_format */
+    _bfd_dummy_target,
+    _bfd_dummy_target,
+  },
+  {                            /* bfd_set_format */
+    bfd_false,
+    ppcboot_mkobject,
+    bfd_false,
+    bfd_false,
+  },
+  {                            /* bfd_write_contents */
+    bfd_false,
+    bfd_true,
+    bfd_false,
+    bfd_false,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (ppcboot),
+  BFD_JUMP_TABLE_COPY (ppcboot),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+  BFD_JUMP_TABLE_SYMBOLS (ppcboot),
+  BFD_JUMP_TABLE_RELOCS (ppcboot),
+  BFD_JUMP_TABLE_WRITE (ppcboot),
+  BFD_JUMP_TABLE_LINK (ppcboot),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL
+};