This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH RFC] bfd/armimxboot.c: new backend for arm imx bootable files


Add a backend for objdump for the bootable files for the Freescale
i.MX6 processors.  Such files are produced by compiling U-Boot
or by using the iMX6 SDK from Freescale, and are understood by
the boot rom of the i.MX6 processors.

* bfd/armimxboot.c: new file.
* bfd/Makefile.am(BFD32_BACKENDS,BFD32_BACKENDS_CFILES): add hooks
* bfd/Makefile.in: regenerate
* bfd/bfd.c(tdata): add arm_imx_boot_data
* bfd/targets.c(_bfd_target_vector): add &arm_imx_boot_vec
* bfd/bfd-in2.h: regenerate
---
This has been tested on a i586 host only and lacks endianness conversion
when reading headers, because I don't know the bfd way to handle that.

 bfd/Makefile.am  |   2 +
 bfd/Makefile.in  |   3 +
 bfd/armimxboot.c | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bfd/bfd-in2.h    |   1 +
 bfd/bfd.c        |   1 +
 bfd/targets.c    |   2 +
 6 files changed, 265 insertions(+)
 create mode 100644 bfd/armimxboot.c

diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 6f64f06..f4a794c 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -263,6 +263,7 @@ BFD32_BACKENDS = \
 	aout-tic30.lo \
 	aout0.lo \
 	aout32.lo \
+	armimxboot.lo \
 	armnetbsd.lo \
 	bout.lo \
 	cf-i386lynx.lo \
@@ -450,6 +451,7 @@ BFD32_BACKENDS_CFILES = \
 	aout-tic30.c \
 	aout0.c \
 	aout32.c \
+	armimxboot.c \
 	armnetbsd.c \
 	bout.c \
 	cf-i386lynx.c \
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 2c385d5..81c2fdb 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -565,6 +565,7 @@ BFD32_BACKENDS = \
 	aout-tic30.lo \
 	aout0.lo \
 	aout32.lo \
+	armimxboot.lo \
 	armnetbsd.lo \
 	bout.lo \
 	cf-i386lynx.lo \
@@ -752,6 +753,7 @@ BFD32_BACKENDS_CFILES = \
 	aout-tic30.c \
 	aout0.c \
 	aout32.c \
+	armimxboot.c \
 	armnetbsd.c \
 	bout.c \
 	cf-i386lynx.c \
@@ -1254,6 +1256,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archures.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armimxboot.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armnetbsd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bfd.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bfdio.Plo@am__quote@
diff --git a/bfd/armimxboot.c b/bfd/armimxboot.c
new file mode 100644
index 0000000..fd1e5cb
--- /dev/null
+++ b/bfd/armimxboot.c
@@ -0,0 +1,256 @@
+/* BFD back end for i.MX 6 bootable files
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   Written by Philippe De Muyter of Macq S.A.
+
+   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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "libaout.h"           /* BFD a.out internal data structures */
+
+struct boot_data {
+	long dest;
+	long image_len;
+	long plugin;
+};
+
+struct ivt_header {
+#define IVT_MAGIC0 0x402000d1
+#define IVT_MAGIC1 0x412000d1
+	long header;
+	long start_addr;
+	long reserv1;
+	long dcd_ptr;
+	long boot_data_ptr;		/* struct boot_data * */
+	long self_ptr;		/* struct ivt_header *, this - boot_data.start = offset linked at */
+	long app_code_csf;
+	long reserv2;
+};
+
+struct arm_imx_boot_data_struct
+{
+  asection *text_section;
+  asection *dcd_section;
+  struct ivt_header ivt;
+};
+
+#define imx_textsec(bfd)  ((bfd)->tdata.arm_imx_boot_data->text_section)
+#define imx_dcdsec(bfd)  ((bfd)->tdata.arm_imx_boot_data->dcd_section)
+
+/* Handle arm i.MX 6 files bootable by the internal Boot ROM.  */
+
+static int read_ivt(bfd *abfd, struct ivt_header *ivt)
+{
+  int val;
+
+  val = bfd_bread ((void *) ivt, (bfd_size_type) sizeof *ivt, abfd);
+  if (val != sizeof *ivt)
+    {
+      /* Too small to be a imx file */
+      return 0;
+    }
+
+  /* Sanity checks */
+  if ((ivt->header != IVT_MAGIC0 && ivt->header != IVT_MAGIC1)
+	|| ivt->reserv1 != 0 || ivt->reserv2 != 0)
+    {
+      return 0;
+    }
+  return 1;
+}
+
+static const bfd_target *
+imx_file_p (bfd *abfd)
+{
+  struct ivt_header ivt;
+  struct boot_data bd;
+  struct arm_imx_boot_data_struct *rawptr;
+  long dcd_header;
+  long dcd_length;
+  bfd_size_type amt;
+  flagword flags;
+  long offset = 0;
+  struct stat statbuf;
+
+  if (bfd_stat (abfd, &statbuf) < 0)
+    return 0;
+
+  if (!read_ivt(abfd, &ivt))
+    {
+      char buf[0x400];
+
+      offset = sizeof buf;
+      if (bfd_seek (abfd, 0, SEEK_SET) != 0
+      || bfd_bread (buf, (bfd_size_type) sizeof buf, abfd) != sizeof buf
+      || buf[0] != 0
+      || memcmp(buf, buf + 1, sizeof buf - 1) != 0
+      || !read_ivt(abfd, &ivt))
+	{
+	  bfd_set_error (bfd_error_wrong_format);
+	  return 0;
+	}
+    }
+
+  if (bfd_seek (abfd, offset + ivt.boot_data_ptr - ivt.self_ptr, SEEK_SET) != 0
+  || bfd_bread ((void *) &bd, (bfd_size_type) sizeof bd, abfd) != sizeof bd)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return 0;
+    }
+
+  if (ivt.dcd_ptr)
+    {
+      if (bfd_seek (abfd, offset + ivt.dcd_ptr - ivt.self_ptr, SEEK_SET) != 0
+      || bfd_bread ((void *) &dcd_header, (bfd_size_type) sizeof dcd_header, abfd) != sizeof dcd_header)
+	{
+	  bfd_set_error (bfd_error_wrong_format);
+	  return 0;
+	}
+      dcd_length = (dcd_header & 0xff00) | ((dcd_header >> 16) & 0xff);
+    }
+  else
+    dcd_length = 0;
+
+  /* OK, we believe you.  You're a imx file (sure, sure).  */
+
+  amt = sizeof (struct arm_imx_boot_data_struct);
+  rawptr = (struct arm_imx_boot_data_struct *) bfd_zmalloc (amt);
+  if (rawptr == NULL)
+    return 0;
+
+  abfd->tdata.arm_imx_boot_data = rawptr;
+
+  rawptr->ivt = ivt; /*Copy the ivt into the tdata part of the bfd */
+
+  /* Create the sections.  */
+
+  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS + SEC_CODE + SEC_READONLY;
+  imx_textsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".text",
+							    flags);
+  if (imx_textsec (abfd) == NULL)
+    goto fail;
+
+  if (dcd_length)
+    {
+      flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS + SEC_DATA + SEC_READONLY;
+      imx_dcdsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".dcd",
+								flags);
+      if (imx_dcdsec (abfd) == NULL)
+	goto fail;
+
+      imx_dcdsec (abfd)->size =  dcd_length;
+
+      imx_dcdsec (abfd)->vma = ivt.dcd_ptr;
+
+      imx_dcdsec (abfd)->filepos = offset + ivt.dcd_ptr - ivt.self_ptr;
+
+      /* Align to word at least */
+      imx_dcdsec (abfd)->alignment_power = 2;
+
+      if (imx_dcdsec (abfd)->size > statbuf.st_size - imx_dcdsec (abfd)->filepos)
+	imx_dcdsec (abfd)->size = statbuf.st_size - imx_dcdsec (abfd)->filepos;
+    }
+
+  imx_textsec (abfd)->size =  bd.image_len;
+
+  imx_textsec (abfd)->vma = ivt.start_addr;
+
+  imx_textsec (abfd)->filepos = offset + ivt.start_addr - ivt.self_ptr;
+
+  /* Align to word at least */
+  imx_textsec (abfd)->alignment_power = 2;
+
+  if (imx_textsec (abfd)->size > statbuf.st_size - imx_textsec (abfd)->filepos)
+    imx_textsec (abfd)->size = statbuf.st_size - imx_textsec (abfd)->filepos;
+
+  bfd_default_set_arch_mach (abfd, bfd_arch_arm, 0L);
+  return abfd->xvec;
+
+ fail:
+  bfd_release (abfd, abfd->tdata.any);
+  abfd->tdata.any = NULL;
+  bfd_section_list_clear (abfd);
+  return NULL;
+}
+
+/* If somebody calls any byte-swapping routines, shoot them.  */
+static void
+swap_abort (void)
+{
+  abort (); /* This way doesn't require any declaration for ANSI to fuck up */
+}
+
+#define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
+#define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
+#define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
+#define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
+#define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
+#define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
+
+const bfd_target arm_imx_boot_vec =
+  {
+    "arm-imx-boot",
+    bfd_target_unknown_flavour,
+    BFD_ENDIAN_LITTLE,		/* target byte order */
+    BFD_ENDIAN_LITTLE,		/* target headers byte order */
+    (HAS_RELOC | EXEC_P |	/* object flags */
+     HAS_LINENO | HAS_DEBUG |
+     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+    (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+     | SEC_RELOC | SEC_HAS_CONTENTS), /* section_flags */
+    0,				/* symbol prefix */
+    ' ',			/* ar_pad_char */
+    16,				/* ar_max_namelen */
+    0,				/* match priority.  */
+    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
+    bfd_getl32, bfd_getl_signed_32, bfd_putl32,	/* 32 bit data */
+    NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
+    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
+    bfd_getl32, bfd_getl_signed_32, bfd_putl32,	/* 32 bit hdrs */
+    NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
+
+    {				/* bfd_check_format */
+      _bfd_dummy_target,		/* unknown format */
+      imx_file_p,		/* object file */
+      _bfd_dummy_target,		/* archive */
+      imx_file_p		/* a imx6 bootable file */
+    },
+    {				/* bfd_set_format */
+      bfd_false, bfd_false,
+      bfd_false, bfd_false
+    },
+    {				/* bfd_write_contents */
+      bfd_false, bfd_false,
+      bfd_false, bfd_false
+    },
+
+    BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+    BFD_JUMP_TABLE_COPY (_bfd_generic),
+    BFD_JUMP_TABLE_CORE (_bfd_nocore),
+    BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+    BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
+    BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+    BFD_JUMP_TABLE_WRITE (_bfd_generic),
+    BFD_JUMP_TABLE_LINK (_bfd_nolink),
+    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+    NULL,
+
+    NULL			/* backend_data */
+  };
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 3886adc..8bc9fbb 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6452,6 +6452,7 @@ struct bfd
   union
     {
       struct aout_data_struct *aout_data;
+      struct arm_imx_boot_data_struct *arm_imx_boot_data;
       struct artdata *aout_ar_data;
       struct _oasys_data *oasys_obj_data;
       struct _oasys_ar_data *oasys_ar_data;
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 8b60911..bfe7a59 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -264,6 +264,7 @@ CODE_FRAGMENT
 .  union
 .    {
 .      struct aout_data_struct *aout_data;
+.      struct arm_imx_boot_data_struct *arm_imx_boot_data;
 .      struct artdata *aout_ar_data;
 .      struct _oasys_data *oasys_obj_data;
 .      struct _oasys_ar_data *oasys_ar_data;
diff --git a/bfd/targets.c b/bfd/targets.c
index 81a3695..642c2ed 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -595,6 +595,7 @@ extern const bfd_target arm_elf32_symbian_be_vec;
 extern const bfd_target arm_elf32_symbian_le_vec;
 extern const bfd_target arm_elf32_vxworks_be_vec;
 extern const bfd_target arm_elf32_vxworks_le_vec;
+extern const bfd_target arm_imx_boot_vec;
 extern const bfd_target arm_pe_be_vec;
 extern const bfd_target arm_pe_le_vec;
 extern const bfd_target arm_pe_epoc_be_vec;
@@ -988,6 +989,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&arm_elf32_symbian_le_vec,
 	&arm_elf32_vxworks_be_vec,
 	&arm_elf32_vxworks_le_vec,
+	&arm_imx_boot_vec,
 	&arm_pe_be_vec,
 	&arm_pe_le_vec,
 	&arm_pe_epoc_be_vec,
-- 
1.8.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]