From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21178 invoked by alias); 17 Jul 2014 14:24:37 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 21151 invoked by uid 89); 17 Jul 2014 14:24:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.5 required=5.0 tests=BAYES_05,SPF_PASS,UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: smtp2.macqel.be Received: from smtp2.macqel.be (HELO smtp2.macqel.be) (109.135.2.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 17 Jul 2014 14:24:33 +0000 Received: from localhost (localhost [127.0.0.1]) by smtp2.macqel.be (Postfix) with ESMTP id 230BC130D4D; Thu, 17 Jul 2014 16:24:30 +0200 (CEST) Received: from smtp2.macqel.be ([127.0.0.1]) by localhost (mail.macqel.be [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MeQSPLDsskd0; Thu, 17 Jul 2014 16:24:24 +0200 (CEST) Received: from mywdesk.macqel (mywdesk.macqel [10.1.40.104]) by smtp2.macqel.be (Postfix) with ESMTP id B0714130994; Thu, 17 Jul 2014 16:24:18 +0200 (CEST) From: Philippe De Muyter To: binutils@sourceware.org Cc: Philippe De Muyter Subject: [PATCH RFC] bfd/armimxboot.c: new backend for arm imx bootable files Date: Thu, 17 Jul 2014 14:24:00 -0000 Message-Id: <1405607049-24093-1-git-send-email-phdm@macqel.be> X-IsSubscribed: yes X-SW-Source: 2014-07/txt/msg00161.txt.bz2 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