diff options
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/elf')
16 files changed, 3628 insertions, 0 deletions
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h new file mode 100644 index 00000000000..2bccf9c073b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf bfd relocation. + * + * \defgroup ELFLOADER MMDSP ELF loader. + */ +#ifndef __INC_CM_ELF_BFD_H +#define __INC_CM_ELF_BFD_H + +#include <cm/inc/cm_type.h> + +/* + * Relocation spcification + */ +enum complain_overflow +{ + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned +}; + +struct reloc_howto_struct +{ + /* The type field has mainly a documentary use - the back end can + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's + what the outside world calls a R_PCRWORD reloc. */ + unsigned int type; + + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift; + + /* The size of the item to be relocated. This is *not* a + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ + int size; + + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize; + + /* Notes that the relocation is relative to the location in the + data section of the addend. The relocation function will + subtract from the relocation value the address of the location + being relocated. */ + t_uint64 pc_relative; + + /* The bit position of the reloc value in the destination. + The relocated value is left shifted by this amount. */ + unsigned int bitpos; + + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; + + void (*special_function)(void); + + /* The textual name of the relocation type. */ + char *name; + + /* Some formats record a relocation addend in the section contents + rather than with the relocation. For ELF formats this is the + distinction between USE_REL and USE_RELA (though the code checks + for USE_REL == 1/0). The value of this field is TRUE if the + addend is recorded with the section contents; when performing a + partial link (ld -r) the section contents (the data) will be + modified. The value of this field is FALSE if addends are + recorded with the relocation (in arelent.addend); when performing + a partial link the relocation will be modified. + All relocations for all ELF USE_RELA targets should set this field + to FALSE (values of TRUE should be looked on with suspicion). + However, the converse is not true: not all relocations of all ELF + USE_REL targets set this field to TRUE. Why this is so is peculiar + to each particular target. For relocs that aren't used in partial + links (e.g. GOT stuff) it doesn't matter what this is set to. */ + char partial_inplace; + + /* src_mask selects the part of the instruction (or data) to be used + in the relocation sum. If the target relocations don't have an + addend in the reloc, eg. ELF USE_REL, src_mask will normally equal + dst_mask to extract the addend from the section contents. If + relocations do have an addend in the reloc, eg. ELF USE_RELA, this + field should be zero. Non-zero values for ELF USE_RELA targets are + bogus as in those cases the value in the dst_mask part of the + section contents should be treated as garbage. */ + t_uint64 src_mask; + + /* dst_mask selects which parts of the instruction (or data) are + replaced with a relocated value. */ + t_uint64 dst_mask; + + /* When some formats create PC relative instructions, they leave + the value of the pc of the place being relocated in the offset + slot of the instruction, so that a PC relative relocation can + be made just by adding in an ordinary offset (e.g., sun3 a.out). + Some formats leave the displacement part of an instruction + empty (e.g., m88k bcs); this flag signals the fact. */ + char pcrel_offset; +}; + +#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h new file mode 100644 index 00000000000..c51845d5f96 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf common definition. + */ +#ifndef __INC_CM_ELF_COMMON_H +#define __INC_CM_ELF_COMMON_H + +#include <cm/engine/component/inc/nmfheaderabi.h> +#include <cm/engine/elf/inc/elfabi.h> +#include <cm/engine/elf/inc/reloc.h> +#include <cm/engine/memory/inc/domain.h> +#include <cm/engine/component/inc/description.h> +#include <cm/engine/utils/inc/string.h> + + +#define MAX_SEGMENT 20 // Just in order to not allocate them dynamically + +struct XXElf; + +/** + * \brief Structure used as database of pushed component. + */ +typedef struct { + t_instance_property instanceProperty; + t_uint32 magicNumber; //!< Magic Number + t_dup_char foundedTemplateName; + t_uint32 minStackSize; //!< Minimum stack size + + struct XXElf *ELF; + + t_elfSegment segments[NUMBER_OF_MMDSP_MEMORY]; + + t_bool temporaryDescription; + + t_memory_reference memoryForConstruct; + t_memory_reference memoryForStart; + t_memory_reference memoryForStop; + t_memory_reference memoryForDestroy; + + t_uint8 requireNumber; //!< Number of interface required by this template + t_uint8 attributeNumber; //!< Number of attributes in this template + t_uint8 propertyNumber; //!< Number of properties in this template + t_uint8 provideNumber; //!< Number of interface provided by this template + + t_interface_require *requires; //!< Array of interface required by this template + t_attribute *attributes; //!< Array of attributes in this template + t_property *properties; //!< Array of properties in this template + t_interface_provide *provides; //!< Array of interface provided by this template + +} t_elfdescription; + +/** + * \brief Temporary structure used as database when pushing component. + */ +typedef struct +{ + const char *elfdata; + const char *sectionData[50]; // YES it must be dynamic, but i'm tired. + + t_bool isExecutable; + + t_sint32 nmfSectionIndex; + const void *relaNmfSegment, *relaNmfSegmentEnd; + const void *relaNmfSegmentSymbols; + const char *relaNmfSegmentStrings; + + const t_elf_component_header*elfheader; + + +} t_tmp_elfdescription; + + +t_cm_error ELF64_LoadComponent( + t_uint16 e_machine, + const char *elfdata, + t_elfdescription **elfhandlePtr, + t_tmp_elfdescription *elftmp); +t_cm_error ELF64_ComputeSegment( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp); + +void ELF64_UnloadComponent( + t_elfdescription *elfhandle); + +t_cm_error ELF64_loadSegment( + t_elfdescription *elfhandle, + t_memory_handle *memory, + t_memory_property property); +t_cm_error ELF64_relocateSegments( + t_memory_handle *memories, + t_elfdescription *elf, + t_memory_property property, + void *cbContext); +t_cm_error ELF64_getRelocationMemory( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_uint32 offsetInNmf, + t_memory_reference *memory); + +const t_elfmemory* MMDSP_getMappingById(t_memory_id memId); +const t_elfmemory* MMDSP_getMappingByName(const char* sectionName, t_instance_property property); +void MMDSP_serializeMemories(t_instance_property property, + const t_elfmemory** codeMemory, const t_elfmemory** thisMemory); +void MMDSP_copySection(t_uint32 origAddr, t_uint32 remoteAddr, t_uint32 sizeInByte); +void MMDSP_bzeroSection(t_uint32 remoteAddr, t_uint32 sizeInByte); +void MMDSP_loadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle); +void MMDSP_unloadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle); + +void MMDSP_copyCode(t_uint64 * remoteAddr64, const char* origAddr, int nb); +void MMDSP_copyData24(t_uint32 * remoteAddr32, const char* origAddr, int nb); +void MMDSP_copyData16(t_uint16 * remoteAddr16, const char* origAddr, int nb); + +t_uint32 cm_resolvSymbol( + void* context, + t_uint32 type, + t_dup_char symbolName, + char* reloc_addr); + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h new file mode 100644 index 00000000000..cbcc6db3b9b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h @@ -0,0 +1,539 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#ifndef _CM_ELF_H +#define _CM_ELF_H 1 + +typedef t_uint16 Elf32_Half; +typedef t_uint16 Elf64_Half; + +typedef t_uint32 Elf32_Word; +typedef t_sint32 Elf32_Sword; +typedef t_uint32 Elf64_Word; +typedef t_sint32 Elf64_Sword; + +typedef t_uint64 Elf32_Xword; +typedef t_sint64 Elf32_Sxword; +typedef t_uint64 Elf64_Xword; +typedef t_sint64 Elf64_Sxword; + +typedef t_uint32 Elf32_Addr; +typedef t_uint64 Elf64_Addr; + +typedef t_uint32 Elf32_Off; +typedef t_uint64 Elf64_Off; + +typedef t_uint16 Elf32_Section; +typedef t_uint16 Elf64_Section; + +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/********************************************* + * Header + *********************************************/ +#define EI_NIDENT (16) //!< Size of e_ident[] + +#define EI_MAG0 0 //!< File identification +#define ELFMAG0 0x7f + +#define EI_MAG1 1 //!< File identification +#define ELFMAG1 'E' + +#define EI_MAG2 2 //!< File identification +#define ELFMAG2 'L' + +#define EI_MAG3 3 //!< File identification +#define ELFMAG3 'F' + +#define EI_CLASS 4 //!< File class +#define ELFCLASSNONE 0 //!< Invalid class +#define ELFCLASS32 1 //!< 32-bit objects +#define ELFCLASS64 2 //!< 64-bit objects + +#define EI_DATA 5 //!< Data encoding +#define ELFDATANONE 0 //!< Invalid data encoding +#define ELFDATA2LSB 1 //!< 2's complement, little endian +#define ELFDATA2MSB 2 //!< 2's complement, big endian + +#define EI_VERSION 6 //!< File version + +#define EI_OSABI 7 //!< OS ABI identification +#define ELFOSABI_NONE 0 //!< No extension +#define ELFOSABI_HPUX 1 //!< HP-UX +#define ELFOSABI_NETBSD 2 //!< NetBSD +#define ELFOSABI_LINUX 3 //!< Linux +#define ELFOSABI_SOLARIS 6 //!< Sun Solaris +#define ELFOSABI_AIX 7 //!< AIX +#define ELFOSABI_IRIX 8 //!< IRIX +#define ELFOSABI_FREEBSD 9 //!< FreeBSD +#define ELFOSABI_TRU64 10 //!< Compaq TRU64 UNIX +#define ELFOSABI_MODESTO 11 //!< Novell Modesto +#define ELFOSABI_OPENBSD 12 //!< Open BSD +#define ELFOSABI_OPENVMS 13 //!< Open VMS +#define ELFOSABI_NSK 14 //!< HP Non-Stop-Kernel + +#define EI_ABIVERSION 8 //!< ABI version + +#define EI_PAD 9 //!< Start of padding byte + + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; //!< The initial bytes mark the file as an object file and provide machine-independent data with which to decode and interpret the file's contents + Elf32_Half e_type; //!< This member identifies the object file type + Elf32_Half e_machine; //!< This member's value specifies the required architecture for an individual file + Elf32_Word e_version; //!< This member identifies the object file version + Elf32_Addr e_entry; //!< This member gives the virtual address to which the system first transfers control, thus starting the process + Elf32_Off e_phoff; //!< This member holds the program header table's file offset in bytes + Elf32_Off e_shoff; //!< This member holds the section header table's file offset in bytes + Elf32_Word e_flags; //!< This member holds processor-specific flags associated with the file + Elf32_Half e_ehsize; //!< This member holds the ELF header's size in bytes + Elf32_Half e_phentsize; //!< This member holds the size in bytes of one entry in the file's program header table; all entries are the same size + Elf32_Half e_phnum; //!< This member holds the number of entries in the program header table + Elf32_Half e_shentsize; //!< This member holds a section header's size in bytes + Elf32_Half e_shnum; //!< This member holds the number of entries in the section header table + Elf32_Half e_shstrndx; //!< This member holds the section header table index of the entry associated with the section name string table +} Elf32_Ehdr; //!< 32bit Entry Header + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; //!< The initial bytes mark the file as an object file and provide machine-independent data with which to decode and interpret the file's contents + Elf64_Half e_type; //!< This member identifies the object file type + Elf64_Half e_machine; //!< This member's value specifies the required architecture for an individual file + Elf64_Word e_version; //!< This member identifies the object file version + Elf64_Addr e_entry; //!< This member gives the virtual address to which the system first transfers control, thus starting the process + Elf64_Off e_phoff; //!< This member holds the program header table's file offset in bytes + Elf64_Off e_shoff; //!< This member holds the section header table's file offset in bytes + Elf64_Word e_flags; //!< This member holds processor-specific flags associated with the file + Elf64_Half e_ehsize; //!< This member holds the ELF header's size in bytes + Elf64_Half e_phentsize; //!< This member holds the size in bytes of one entry in the file's program header table; all entries are the same size + Elf64_Half e_phnum; //!< This member holds the number of entries in the program header table + Elf64_Half e_shentsize; //!< This member holds a section header's size in bytes + Elf64_Half e_shnum; //!< This member holds the number of entries in the section header table + Elf64_Half e_shstrndx; //!< This member holds the section header table index of the entry associated with the section name string table +} Elf64_Ehdr; //!< 64bit Entry Header + +/* + * e_type + */ +#define ET_NONE 0 //!< No file type +#define ET_REL 1 //!< Relocatable file +#define ET_EXEC 2 //!< Executable file +#define ET_DYN 3 //!< Shared object file +#define ET_CORE 4 //!< Core file +#define ET_LOOS 0xfe00 //!< Operating system-specific +#define ET_HIOS 0xfeff //!< Operating system-specific +#define ET_LOPROC 0xff00 //!< Processor-specific +#define ET_HIPROC 0xffff //!< Processor-specific + +/* + * e_machine + */ +#define EM_NONE 0 //!< No machine +#define EM_M32 1 //!< AT&T WE 32100 +#define EM_SPARC 2 //!< SUN SPARC +#define EM_386 3 //!< Intel 80386 +#define EM_68K 4 //!< Motorola 68000 +#define EM_88K 5 //!< Motorola 88000 +#define EM_860 7 //!< Intel 80860 +#define EM_MIPS 8 //!< MIPS I architecture +#define EM_S370 9 //!< IBM System/370 +#define EM_MIPS_RS3_LE 10 //!< MIPS R3000 little-endian +#define EM_PARISC 15 //!< HPPA +#define EM_VPP500 17 //!< Fujitsu VPP500 +#define EM_SPARC32PLUS 18 //!< Enhanced instruction set SPARC +#define EM_960 19 //!< Intel 80960 +#define EM_PPC 20 //!< PowerPC +#define EM_PPC64 21 //!< 64-bit PowerPC +#define EM_S390 22 //!< IBM System/390 Processor +#define EM_V800 36 //!< NEC V800 +#define EM_FR20 37 //!< Fujitsu FR20 +#define EM_RH32 38 //!< TRW RH-32 +#define EM_RCE 39 //!< Motorola RCE +#define EM_ARM 40 //!< Advanced RISC Machines ARM +#define EM_FAKE_ALPHA 41 //!< Digital Alpha +#define EM_SH 42 //!< Hitachi SH +#define EM_SPARCV9 43 //!< SPARC Version 9 +#define EM_TRICORE 44 //!< Siemens TriCore embedded processor +#define EM_ARC 45 //!< Argonaut RISC Core, Argonaut Technologies Inc +#define EM_H8_300 46 //!< Hitachi H8/300 +#define EM_H8_300H 47 //!< Hitachi H8/300H +#define EM_H8S 48 //!< Hitachi H8S +#define EM_H8_500 49 //!< Hitachi H8/500 +#define EM_IA_64 50 //!< Intel IA-64 processor architecture +#define EM_MIPS_X 51 //!< Stanford MIPS-X +#define EM_COLDFIRE 52 //!< Motorola ColdFire +#define EM_68HC12 53 //!< Motorola M68HC12 +#define EM_MMA 54 //!< Fujitsu MMA Multimedia Accelerator +#define EM_PCP 55 //!< Siemens PCP +#define EM_NCPU 56 //!< Sony nCPU embedded RISC processor +#define EM_NDR1 57 //!< Denso NDR1 microprocessor +#define EM_STARCORE 58 //!< Motorola Start*Core processor +#define EM_ME16 59 //!< Toyota ME16 processor +#define EM_ST100 60 //!< STMicroelectronics ST100 processor +#define EM_TINYJ 61 //!< Advanced Logic Corp. TinyJ embedded processor family +#define EM_X86_64 62 //!< AMD x86-64 architecture +#define EM_PDSP 63 //!< Sony DSP Processor +#define EM_PDP10 64 //!< Digital Equipment Corp. PDP-10 +#define EM_PDP11 65 //!< Digital Equipment Corp. PDP-11 +#define EM_FX66 66 //!< Siemens FX66 microcontroller +#define EM_ST9PLUS 67 //!< STMicroelectronics ST9+ 8/16 bit microcontroller +#define EM_ST7 68 //!< STMicroelectronics ST7 8-bit microcontroller +#define EM_68HC16 69 //!< Motorola MC68HC16 Microcontroller +#define EM_68HC11 70 //!< Motorola MC68HC11 Microcontroller +#define EM_68HC08 71 //!< Motorola MC68HC08 Microcontroller +#define EM_68HC05 72 //!< Motorola MC68HC05 Microcontroller +#define EM_SVX 73 //!< Silicon Graphics SVx +#define EM_ST19 74 //!< STMicroelectronics ST19 8-bit microcontroller +#define EM_VAX 75 //!< Digital VAX +#define EM_CRIS 76 //!< Axis Communications 32-bit embedded processor +#define EM_JAVELIN 77 //!< Infifineon Technologies 32-bit embedded processor +#define EM_FIREPATH 78 //!< Element 14 64-bit DSP Processor +#define EM_ZSP 79 //!< LSI Logic 16-bit DSP Processor +#define EM_MMIX 80 //!< Donald Knuth's educational 64-bit processor +#define EM_HUANY 81 //!< Harvard University machine-independent object files +#define EM_PRISM 82 //!< SiTera Prism +#define EM_AVR 83 //!< Atmel AVR 8-bit microcontroller +#define EM_FR30 84 //!< Fujitsu FR30 +#define EM_D10V 85 //!< Mitsubishi D10V +#define EM_D30V 86 //!< Mitsubishi D30V +#define EM_V850 87 //!< NEC v850 +#define EM_M32R 88 //!< Mitsubishi M32R +#define EM_MN10300 89 //!< Matsushita MN10300 +#define EM_MN10200 90 //!< Matsushita MN10200 +#define EM_PJ 91 //!< picoJava +#define EM_OPENRISC 92 //!< OpenRISC 32-bit embedded processor +#define EM_ARC_A5 93 //!< ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) +#define EM_XTENSA 94 //!< Tensilica Xtensa Architecture +#define EM_VIDEOCORE 95 //!< Alphamosaic VideoCore processor +#define EM_TMM_GPP 96 //!< Thompson Multimedia General Purpose Processor +#define EM_NS32K 97 //!< National Semiconductor 32000 series +#define EM_TPC 98 //!< Tenor Network TPC processor +#define EM_SNP1K 99 //!< Trebia SNP 1000 processor +#define EM_ST200 100 //!< STMicroelectronics (www.st.com) ST200 microcontroller +#define EM_IP2K 101 //!< Ubicom IP2xxx microcontroller family +#define EM_MAX 102 //!< MAX Processor +#define EM_CR 103 //!< National Semiconductor CompactRISC microprocessor +#define EM_F2MC16 104 //!< Fujitsu F2MC16 +#define EM_MSP430 105 //!< Texaxas Instruments embedded microcontroller msp430 +#define EM_BLACKFIN 106 //!< Analog Devices Blackfin (DSP) processor +#define EM_SE_C33 107 //!< S1C33 Family of Seiko Epspson processors +#define EM_SEP 108 //!< Sharp embedded microprocessor +#define EM_ARCA 109 //!< Arca RISC Microprocessor +#define EM_UNICORE 110 //!< Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University +#define EM_EXCESS 111 //!< eXcess: 16/32/64-bit configurable embedded CPU +#define EM_DXP 112 //!< Icera Semiconductor Inc. Deep Execution Processor +#define EM_ALTERA_NIOS2 113 //!< Altera Nios II soft-core processor +#define EM_CRX 114 //!< National Semiconductor CompactRISC CRX microprocessor +#define EM_XGATE 115 //!< Motorola XGATE embedded processor +#define EM_C166 116 //!< Infifineon C16x/XC16x processor +#define EM_M16C 117 //!< Renesas M16C series microprocessors +#define EM_DSPIC30F 118 //!< Microchip Technology dsPIC30F Digital Signal Controller +#define EM_CE 119 //!< Freescale Communication Engine RISC core +#define EM_M32C 120 //!< Renesas M32C series microprocessors +#define EM_TSK3000 131 //!< Altium TSK3000 core +#define EM_RS08 132 //!< Freescale RS08 embedded processor +#define EM_ECOG2 134 //!< Cyan Technology eCOG2 microprocessor +#define EM_SCORE7 135 //!< Sunplus S+core7 RISC processor +#define EM_DSP24 136 //!< New Japan Radio (NJR) 24-bit DSP Processor +#define EM_VIDEOCORE3 137 //!< Broadcom VideoCore III processor +#define EM_LATTICEMICO32 138 //!< RISC processor for Lattice FPGA architecture +#define EM_SE_C17 139 //!< Seiko Epspson C17 family +#define EM_TI_C6000 140 //!< The Texaxas Instruments TMS320C6000 DSP family +#define EM_TI_C2000 141 //!< The Texaxas Instruments TMS320C2000 DSP family +#define EM_TI_C5500 142 //!< The Texaxas Instruments TMS320C55x DSP family +#define EM_MMDSP_PLUS 160 //!< STMicroelectronics 64bit VLIW Data Signal Processor +#define EM_CYPRESS_M8C 161 //!< Cypress M8C microprocessor +#define EM_R32C 162 //!< Renesas R32C series microprocessors +#define EM_TRIMEDIA 163 //!< NXP Semiconductors TriMedia architecture family +#define EM_QDSP6 164 //!< QUALCOMM DSP6 Processor +#define EM_8051 165 //!< Intel 8051 and variants +#define EM_STXP7X 166 //!< STMicroelectronics STxP7x family of configurable and extensible RISC processors +#define EM_NDS32 167 //!< Andes Technology compact code size embedded RISC processor family +#define EM_ECOG1 168 //!< Cyan Technology eCOG1X family +#define EM_ECOG1X 168 //!< Cyan Technology eCOG1X family +#define EM_MAXQ30 169 //!< Dallas Semiconductor MAXQ30 Core Micro-controllers +#define EM_XIMO16 170 //!< New Japan Radio (NJR) 16-bit DSP Processor +#define EM_MANIK 171 //!< M2000 Reconfigurable RISC Microprocessor +#define EM_CRAYNV2 172 //!< Cray Inc. NV2 vector architecture +#define EM_RX 173 //!< Renesas RX family +#define EM_METAG 174 //!< Imagination Technologies META processor architecture +#define EM_MCST_ELBRUS 175 //!< MCST Elbrus general purpose hardware architecture +#define EM_ECOG16 176 //!< Cyan Technology eCOG16 family +#define EM_CR16 177 //!< National Semiconductor CompactRISC CR16 16-bit microprocessor +#define EM_ETPU 178 //!< Freescale Extended Time Processing Unit +#define EM_SLE9X 179 //!< Infifineon Technologies SLE9X core +#define EM_AVR32 185 //!< Atmel Corporation 32-bit microprocessor family +#define EM_STM8 186 //!< STMicroeletronics STM8 8-bit microcontroller +#define EM_TILE64 187 //!< Tilera TILE64 multicore architecture family +#define EM_TILEPRO 188 //!< Tilera TILEPro multicore architecture family +#define EM_MICROBLAZE 189 //!< Xilinx MicroBlaze 32-bit RISC soft processor core +#define EM_CUDA 190 //!< NVIDIA CUDA architecture +#define EM_TILEGX 191 //!< Tilera TILE-Gx multicore architecture family + +/* + * e_version (version) + */ +#define EV_NONE 0 //!< Invalid version +#define EV_CURRENT 1 //!< Current version + + +/********************************************* + * Section + *********************************************/ +typedef struct +{ + Elf32_Word sh_name; //!< This member specifies the name of the section + Elf32_Word sh_type; //!< This member categorizes the section's contents and semantics + Elf32_Word sh_flags; //!< Sections support 1-bit flags that describe miscellaneous attributes + Elf32_Addr sh_addr; //!< If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside + Elf32_Off sh_offset; //!< This member's value gives the byte offset from the beginning of the file to the first byte in the section + Elf32_Word sh_size; //!< This member gives the section's size in bytes + Elf32_Word sh_link; //!< This member holds a section header table index link, whose interpretation depends on the section type + Elf32_Word sh_info; //!< This member holds extra information, whose interpretation depends on the section type + Elf32_Word sh_addralign; //!< Some sections have address alignment constraints + Elf32_Word sh_entsize; //!< Some sections hold a table of fixed-size entries, such as a symbol table +} Elf32_Shdr; //!< 32bit Section header + +typedef struct +{ + Elf64_Word sh_name; //!< This member specifies the name of the section + Elf64_Word sh_type; //!< This member categorizes the section's contents and semantics + Elf64_Xword sh_flags; //!< Sections support 1-bit flags that describe miscellaneous attributes + Elf64_Addr sh_addr; //!< If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside + Elf64_Off sh_offset; //!< This member's value gives the byte offset from the beginning of the file to the first byte in the section + Elf64_Xword sh_size; //!< This member gives the section's size in bytes + Elf64_Word sh_link; //!< This member holds a section header table index link, whose interpretation depends on the section type + Elf64_Word sh_info; //!< This member holds extra information, whose interpretation depends on the section type + Elf64_Xword sh_addralign; //!< Some sections have address alignment constraints + Elf64_Xword sh_entsize; //!< Some sections hold a table of fixed-size entries, such as a symbol table +} Elf64_Shdr; //!< 64bit Section header + +/* + * Special Section Indexes + */ +#define SHN_UNDEF 0 //!< This value marks an undefined, missing, irrelevant, or otherwise meaningless section reference +#define SHN_LORESERVE 0xff00 //!< This value specifies the lower bound of the range of reserved indexes +#define SHN_LOPROC 0xff00 //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHN_HIPROC 0xff1f //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHN_LOOS 0xff20 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHN_HIOS 0xff3f //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHN_ABS 0xfff1 //!< This value specifies absolute values for the corresponding reference +#define SHN_COMMON 0xfff2 //!< Symbols defined relative to this section are common symbols +#define SHN_XINDEX 0xffff //!< This value is an escape value +#define SHN_HIRESERVE 0xffff //!< This value specifies the upper bound of the range of reserved indexes + +/* + * sh_type + */ +#define SHT_NULL 0 //!< This value marks the section header as inactive +#define SHT_PROGBITS 1 //!< The section holds information defined by the program +#define SHT_SYMTAB 2 //!< These sections hold a symbol table +#define SHT_STRTAB 3 //!< The section holds a string table +#define SHT_RELA 4 //!< The section holds relocation entries with explicit addends, such as type Elf32_Rela for the 32-bit class of object files or type Elf64_Rela for the 64-bit class of object files +#define SHT_HASH 5 //!< The section holds a symbol hash table +#define SHT_DYNAMIC 6 //!< The section holds information for dynamic linking +#define SHT_NOTE 7 //!< The section holds information that marks the file in some way +#define SHT_NOBITS 8 //!< A section of this type occupies no space in the file but otherwise resembles SHT_PROGBITS +#define SHT_REL 9 //!< The section holds relocation entries without explicit addends, such as type Elf32_Rel for the 32-bit class of object files or type Elf64_Rel for the 64-bit class of object files +#define SHT_SHLIB 10 //!< This section type is reserved but has unspecified semantics +#define SHT_DYNSYM 11 //!< +#define SHT_INIT_ARRAY 14 //!< This section contains an array of pointers to initialization functions +#define SHT_FINI_ARRAY 15 //!< This section contains an array of pointers to termination functions +#define SHT_PREINIT_ARRAY 16 //!< This section contains an array of pointers to functions that are invoked before all other initialization functions +#define SHT_GROUP 17 //!< This section defines a section group +#define SHT_SYMTAB_SHNDX 18 //!< This section is associated with a section of type SHT_SYMTAB and is required if any of the section header indexes referenced by that symbol table contain the escape value SHN_XINDEX +#define SHT_LOOS 0x60000000 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHT_HIOS 0x6fffffff //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHT_LOPROC 0x70000000 //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHT_HIPROC 0x7fffffff //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHT_LOUSER 0x80000000 //!< This value specifies the upper bound of the range of indexes reserved for application programs +#define SHT_HIUSER 0x8fffffff //!< This value specifies the upper bound of the range of indexes reserved for application programs + +/* + * sh_flags + */ +#define SHF_WRITE 0x1 //!< The section contains data that should be writable during process execution +#define SHF_ALLOC 0x2 //!< The section occupies memory during process execution +#define SHF_EXECINSTR 0x4 //!< The section contains executable machine instructions +#define SHF_MERGE 0x10 //!< The data in the section may be merged to eliminate duplication +#define SHF_STRINGS 0x20 //!< The data elements in the section consist of null-terminated character strings +#define SHF_INFO_LINK 0x40 //!< The sh_info field of this section header holds a section header table index +#define SHF_LINK_ORDER 0x80 //!< This flag adds special ordering requirements for link editors +#define SHF_OS_NONCONFORMING 0x100 //!< This section requires special OS-specific processing (beyond the standard linking rules) to avoid incorrect behavior +#define SHF_GROUP 0x200 //!< This section is a member (perhaps the only one) of a section group +#define SHF_TLS 0x400 //!< This section holds Thread-Local Storage, meaning that each separate execution flow has its own distinct instance of this data +#define SHF_MASKOS 0x0ff00000 //!< All bits included in this mask are reserved for operating system-specific semantics +#define SHF_MASKPROC 0xf0000000 //!< All bits included in this mask are reserved for processor-specific semantics + + +/********************************************* + * Symbol + *********************************************/ +typedef struct +{ + Elf32_Word st_name; //!< This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names + Elf32_Addr st_value; //!< This member gives the value of the associated symbol + Elf32_Word st_size; //!< Many symbols have associated sizes + unsigned char st_info; //!< This member specifies the symbol's type and binding attributes + unsigned char st_other; //!< This member currently specifies a symbol's visibility + Elf32_Section st_shndx; //!< Every symbol table entry is defined in relation to some section +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; //!< This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names + unsigned char st_info; //!< This member specifies the symbol's type and binding attributes + unsigned char st_other; //!< This member currently specifies a symbol's visibility + Elf64_Section st_shndx; //!< Every symbol table entry is defined in relation to some section + Elf64_Addr st_value; //!< This member gives the value of the associated symbol + Elf64_Xword st_size; //!< Many symbols have associated sizes +} Elf64_Sym; + +/* + * st_info + */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +#define ELF64_ST_BIND(i) ((i)>>4) +#define ELF64_ST_TYPE(i) ((i)&0xf) +#define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + + +/* st_info (symbol binding) */ +#define STB_LOCAL 0 //!< Local symbols are not visible outside the object file containing their definition +#define STB_GLOBAL 1 //!< Global symbols are visible to all object files being combined +#define STB_WEAK 2 //!< Weak symbols resemble global symbols, but their definitions have lower precedence +#define STB_LOOS 10 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STB_HIOS 12 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STB_LOPROC 13 //!< Values in this inclusive range are reserved for processor-specific semantics +#define STB_HIPROC 15 //!< Values in this inclusive range are reserved for processor-specific semantics + +/* st_info (symbol type) */ +#define STT_NOTYPE 0 //!< The symbol's type is not specified +#define STT_OBJECT 1 //!< The symbol is associated with a data object, such as a variable, an array, and so on +#define STT_FUNC 2 //!< The symbol is associated with a function or other executable code +#define STT_SECTION 3 //!< The symbol is associated with a section +#define STT_FILE 4 //!< Conventionally, the symbol's name gives the name of the source file associated with the object file +#define STT_COMMON 5 //!< The symbol labels an uninitialized common block +#define STT_TLS 6 //!< The symbol specifies a Thread-Local Storage entity +#define STT_LOOS 10 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STT_HIOS 12 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STT_LOPROC 13 //!< Values in this inclusive range are reserved for processor-specific semantics +#define STT_HIPROC 15 //!< Values in this inclusive range are reserved for processor-specific semantics + +/* + * st_other + */ +#define ELF32_ST_VISIBILITY(o) ((o)&0x3) +#define ELF64_ST_VISIBILITY(o) ((o)&0x3) + + +#define STV_DEFAULT 0 //!< The visibility of symbols with the STV_DEFAULT attribute is as specified by the symbol's binding type +#define STV_INTERNAL 1 //!< A symbol defined in the current component is protected if it is visible in other components but not preemptable, meaning that any reference to such a symbol from within the defining component must be resolved to the definition in that component, even if there is a definition in another component that would preempt by the default rules +#define STV_HIDDEN 2 //!< A symbol defined in the current component is hidden if its name is not visible to other components +#define STV_PROTECTED 3 //!< The meaning of this visibility attribute may be defined by processor supplements to further constrain hidden symbols + + +/********************************************* + * Relocation + *********************************************/ +typedef struct +{ + Elf32_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf32_Word r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply +} Elf32_Rel; //!< 32bits Relocation Entries + +typedef struct +{ + Elf64_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf64_Xword r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply +} Elf64_Rel; //!< 32bits Relocation Entries + +typedef struct +{ + Elf32_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf32_Word r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply + Elf32_Sword r_addend; //!< This member specifies a constant addend used to compute the value to be stored into the relocatable field +} Elf32_Rela; //!< 32bits Relocation Addend Entries + +typedef struct +{ + Elf64_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf64_Xword r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply + Elf64_Sxword r_addend; //!< This member specifies a constant addend used to compute the value to be stored into the relocatable field +} Elf64_Rela; //!< 32bits Relocation Addend Entries + + +/* + * r_info + */ +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + +#define ELF64_R_SYM(i) ((i)>>32) +#define ELF64_R_TYPE(i) ((i)&0xffffffffL) +#define ELF64_R_INFO(s,t) (((s)<<32)+((t)&0xffffffffL)) + + + +/********************************************* + * Program + *********************************************/ +typedef struct +{ + Elf32_Word p_type; //!< This member tells what kind of segment this array element describes or how to interpret the array element's information + Elf32_Off p_offset; //!< This member gives the offset from the beginning of the file at which the first byte of the segment resides + Elf32_Addr p_vaddr; //!< This member gives the virtual address at which the first byte of the segment resides in memory + Elf32_Addr p_paddr; //!< On systems for which physical addressing is relevant, this member is reserved for the segment's physical address + Elf32_Word p_filesz; //!< This member gives the number of bytes in the file image of the segment; it may be zero + Elf32_Word p_memsz; //!< This member gives the number of bytes in the memory image of the segment; it may be zero + Elf32_Word p_flags; //!< This member gives flags relevant to the segment + Elf32_Word p_align; //!< As ``Program Loading'' describes in this chapter of the processor supplement, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size +} Elf32_Phdr; //!< 32bits Program header + +typedef struct +{ + Elf64_Word p_type; //!< This member tells what kind of segment this array element describes or how to interpret the array element's information + Elf64_Word p_flags; //!< This member gives flags relevant to the segment + Elf64_Off p_offset; //!< This member gives the offset from the beginning of the file at which the first byte of the segment resides + Elf64_Addr p_vaddr; //!< This member gives the virtual address at which the first byte of the segment resides in memory + Elf64_Addr p_paddr; //!< On systems for which physical addressing is relevant, this member is reserved for the segment's physical address + Elf64_Xword p_filesz; //!< This member gives the number of bytes in the file image of the segment; it may be zero + Elf64_Xword p_memsz; //!< This member gives the number of bytes in the memory image of the segment; it may be zero + Elf64_Xword p_align; //!< As ``Program Loading'' describes in this chapter of the processor supplement, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size +} Elf64_Phdr; //!< 64bits Program header + +/* + * p_type + */ +#define PT_NULL 0 //!< The array element is unused; other members' values are undefined +#define PT_LOAD 1 //!< The array element specifies a loadable segment, described by p_filesz and p_memsz +#define PT_DYNAMIC 2 //!< The array element specifies dynamic linking information +#define PT_INTERP 3 //!< The array element specifies the location and size of a null-terminated path name to invoke as an interpreter +#define PT_NOTE 4 //!< The array element specifies the location and size of auxiliary information +#define PT_SHLIB 5 //!< This segment type is reserved but has unspecified semantics +#define PT_PHDR 6 //!< The array element, if present, specifies the location and size of the program header table itself, both in the file and in the memory image of the program +#define PT_TLS 7 //!< The array element specifies the Thread-Local Storage template +#define PT_LOOS 0x60000000 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define PT_HIOS 0x6fffffff //!< Values in this inclusive range are reserved for operating system-specific semantics +#define PT_LOPROC 0x70000000 //!< Values in this inclusive range are reserved for processor-specific semantics +#define PT_HIPROC 0x7fffffff //!< Values in this inclusive range are reserved for processor-specific semantics + +/* + * p_flags + */ +#define PF_X (1 << 0) //!< Execute +#define PF_W (1 << 1) //!< Write +#define PF_R (1 << 2) //!< Read +#define PF_MASKOS 0x0ff00000 //!< Unspecified +#define PF_MASKPROC 0xf0000000 //!< Unspecified + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h new file mode 100644 index 00000000000..cce6d158b4e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf loder internal methods. + * + * \defgroup ELFLOADER MMDSP ELF loader. + */ +#ifndef __INC_CM_ELFLOADER_H +#define __INC_CM_ELFLOADER_H + +#include <cm/engine/elf/inc/common.h> + +/*! + * \internal + * \brief ELF Parsing & checking + * \ingroup ELFLOADER + */ +t_cm_error cm_ELF_CheckFile( + const char *elfdata, + t_bool temporaryDescription, + t_elfdescription **elfhandlePtr); + +void cm_ELF_ReleaseDescription( + t_uint32 requireNumber, t_interface_require *requires, + t_uint32 attributeNumber, t_attribute *attributes, + t_uint32 propertyNumber, t_property *properties, + t_uint32 provideNumber, t_interface_provide *provides); + +/*! + * \internal + * \brief ELF closing + * \ingroup ELFLOADER + */ +void cm_ELF_CloseFile( + t_bool temporaryDescription, + t_elfdescription *elfhandle); + +/*! + * \internal + * \brief Load a component template shared memories. + * + * \note In case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeTemplate. + */ +t_cm_error cm_ELF_LoadTemplate( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton); + +/*! + * \internal + * \brief Clean cache memory of a component template shared code. + */ +void cm_ELF_FlushTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + +void cm_ELF_FlushInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); + +/*! + * \internal + * \brief Load a component instance private memories. + * + * \note In case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeInstance. + */ +t_cm_error cm_ELF_LoadInstance( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton); + +void cm_ELF_FreeInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); +void cm_ELF_FreeTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + + +t_cm_error cm_ELF_relocateSharedSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext); +t_cm_error cm_ELF_relocatePrivateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext); +void cm_ELF_performRelocation( + t_uint32 type, + const char *symbol_name, + t_uint32 symbol_addr, + char *reloc_addr); +t_cm_error cm_ELF_GetMemory( + t_elfdescription *elf, + t_tmp_elfdescription *elftmp, + t_uint32 address, + t_memory_purpose purpose, + t_memory_reference *memory); + + +#include <cm/engine/component/inc/component_type.h> + +t_cm_error cm_DSPABI_AddLoadMap( + t_cm_domain_id domainId, + const char* templateName, + const char* localname, + t_memory_handle *memories, + void *componentHandle); +t_cm_error cm_DSPABI_RemoveLoadMap( + t_cm_domain_id domainId, + const char* templateName, + t_memory_handle *memories, + const char* localname, + void *componentHandle); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h new file mode 100644 index 00000000000..9eab94f173c --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf memory. + */ +#ifndef __INC_CM_ELF_MEMORY_H +#define __INC_CM_ELF_MEMORY_H + +#include <cm/engine/dsp/inc/dsp.h> + +/** + * \brief Memory identifier + */ +typedef t_uint8 t_memory_id; + +/** + * \brief Memory property + */ +typedef enum { + MEM_FOR_MULTIINSTANCE, + MEM_FOR_SINGLETON, + MEM_FOR_LAST +} t_instance_property; + +/** + * \brief Memory prupose (for processor with different address space for code and data/ + */ +typedef enum { + MEM_CODE, + MEM_DATA +} t_memory_purpose; + +/** + * \brief Memory property + */ +typedef enum { + MEM_PRIVATE, + MEM_SHARABLE, +} t_memory_property; + +/** + * \brief Elf memory mapping description + */ +typedef struct +{ + t_memory_id id; + t_dsp_memory_type_id dspMemType; + t_uint32 startAddr; + t_cm_memory_alignment memAlignement; + t_memory_property property; + t_memory_purpose purpose; + t_uint8 fileEntSize; + t_uint8 memEntSize; + char* memoryName; +} t_elfmemory; + +#define NUMBER_OF_MMDSP_MEMORY 15 + +/* + * \brief Elf segment description + */ +typedef struct { + // Data in Bytes + t_uint32 sumSize; + t_bool sumSizeSetted; + t_cm_logical_address hostAddr; // Valid only if section Load in memory + t_uint32 maxAlign; + // Data in word + t_uint32 mpcAddr; // Valid only if section Load in memory +} t_elfSegment; + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h new file mode 100644 index 00000000000..bb65c0b1244 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf writer internal methods. + * + * \defgroup LOADMAP MMDSP ELF writer (a linker in fact). + */ +#ifndef __INC_CM_LOADMAP_H +#define __INC_CM_LOADMAP_H + +#include <cm/inc/cm_type.h> + +/* + * Align with loadmap : + * https://codex.cro.st.com/wiki/index.php?pagename=Specification%2FLoadmap%2Fv1.2&group_id=310 + */ +#define LOADMAP_MAGIC_NUMBER 0xFBBF + +#define LOADMAP_VERSION_MSB 1 +#define LOADMAP_VERSION_LSB 2 + +struct LoadMapItem +{ + const char* pSolibFilename; // Filename of shared library object + void* pAddrProg; // Load address of program section + void* pAddrEmbProg; // Load address of embedded program section + void* pThis; // Data base address of component instance + void* pARMThis; // ARM component debug ID + const char* pComponentName; // Pretty name of the component instance, NULL if none. + struct LoadMapItem* pNextItem;// Pointer on the next list item, NULL if last one. + void* pXROM; // Start address of XROM + void* pYROM; // Start address of YROM +}; + +struct LoadMapHdr +{ + t_uint16 nMagicNumber; // Equal to 0xFBBF. + t_uint16 nVersion; // The version of the load map format. + t_uint32 nRevision; // A counter incremented at each load map list modification. + struct LoadMapItem* pFirstItem;// Pointer on the first item, NULL if no shared library loaded. +}; + +#endif /* __INC_CM_LOADMAP_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h new file mode 100644 index 00000000000..1662def6c1a --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief MMDSP elf. + */ +#ifndef __INC_CM_ELF_MMDSP_H +#define __INC_CM_ELF_MMDSP_H + +#include <cm/engine/elf/inc/common.h> + +#define CODE_MEMORY_INDEX 0 +#define ECODE_MEMORY_INDEX 7 + +#define XROM_MEMORY_INDEX 1 +#define YROM_MEMORY_INDEX 2 +#define PRIVATE_DATA_MEMORY_INDEX 8 +#define SHARE_DATA_MEMORY_INDEX 1 + +/* + * Relocation + */ +#define R_MMDSP_IMM16 5 +#define R_MMDSP_IMM20_16 6 +#define R_MMDSP_IMM20_4 7 +#define R_MMDSP_24 13 + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h new file mode 100644 index 00000000000..718b7f61ceb --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief MPC Abraction Layer. + * + * \defgroup MPCAL MPC Abraction Layer. + */ +#ifndef __INC_CM_DSP_MPCAL_H +#define __INC_CM_DSP_MPCAL_H + +#include <cm/inc/cm_type.h> +#include <share/inc/nmf.h> + +#include <cm/engine/elf/inc/common.h> + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h new file mode 100644 index 00000000000..b38be48d689 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf relocation. + */ +#ifndef __INC_CM_ELF_RELOC_H +#define __INC_CM_ELF_RELOC_H + + +void MMDSP_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr, + const char* inPlaceAddr, + t_uint32 reloc_offset); + +/* + * + * Return: + * 0x0 returned if symbol not found + * 0xFFFFFFFE returned if out of memory + * 0xFFFFFFFF returned if symbol found in static required binding + */ +typedef t_uint32 (*CBresolvSymbol)( + void* context, + t_uint32 type, + const char* symbolName, + char* reloc_addr); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c new file mode 100644 index 00000000000..2e0f5928ffd --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include <cm/engine/elf/inc/common.h> +#include <cm/engine/elf/inc/elfabi.h> + +#include <cm/engine/utils/inc/swap.h> +#include <cm/engine/trace/inc/trace.h> + +typedef Elf64_Half ElfXX_Half; +typedef Elf64_Word ElfXX_Word; +typedef Elf64_Addr ElfXX_Addr; +typedef Elf64_Off ElfXX_Off; + +typedef Elf64_Xword ElfXX_Xword; + +typedef Elf64_Ehdr ElfXX_Ehdr; +typedef Elf64_Shdr ElfXX_Shdr; +typedef Elf64_Sym ElfXX_Sym; +typedef Elf64_Rela ElfXX_Rela; + +#undef ELFXX_R_SYM +#define ELFXX_R_SYM ELF64_R_SYM +#undef ELFXX_R_TYPE +#define ELFXX_R_TYPE ELF64_R_TYPE +#undef ELFXX_R_INFO +#define ELFXX_R_INFO ELF64_R_INFO + +// TODO Here we assume big endian (MMDSP !) +static Elf64_Half swapHalf(Elf64_Half half) +{ + return (Elf64_Half)swap16(half); +} + +static Elf64_Word swapWord(Elf64_Word word) +{ + return (Elf64_Word)swap32(word); +} + +static Elf64_Xword swapXword(Elf64_Xword xword) +{ + return (Elf64_Xword)swap64(xword); +} + +#include "elfxx.c" diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c new file mode 100644 index 00000000000..274a1b6b59f --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -0,0 +1,773 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include <cm/engine/elf/inc/elfapi.h> +#include <cm/engine/elf/inc/mpcal.h> +#include <cm/inc/cm_def.h> + +//#include <cm/engine/component/inc/introspection.h> + +#include <cm/engine/utils/inc/mem.h> +#include <cm/engine/trace/inc/trace.h> +#include <cm/engine/utils/inc/swap.h> +#include <cm/engine/utils/inc/string.h> + +static void* getElfHeaderReference(t_tmp_elfdescription *elftmp, void* hdrref) +{ + if(hdrref != NULL) + return (void*)((int)swap32((t_uint32)hdrref) + (int)elftmp->elfheader); + else + return NULL; +} + +static t_dup_char copyElfString(t_tmp_elfdescription *elftmp, char* idx) +{ + return cm_StringDuplicate((char*)getElfHeaderReference(elftmp, (void*)idx)); +} + +static t_cm_error getMemoryOffset( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_memory_purpose purpose, + const t_uint32 *addressInNmf, + t_memory_reference *memory) { + + if(elftmp->isExecutable) { + return cm_ELF_GetMemory(elfhandle, elftmp, + swap32(*addressInNmf), + purpose, + memory); + } else { + return ELF64_getRelocationMemory(elfhandle, elftmp, + (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader, + memory); + } +} + +static t_cm_error getAdressForExecutableOffsetElsewhere( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + const t_uint32 *addressInNmf, + t_memory_reference *memory) { + t_uint32 address; + + address = swap32(*addressInNmf); + if(address == 0xFFFFFFFF) + { + memory->offset = 0x0; + memory->memory = NULL; + return CM_OK; + } + + if(elftmp->isExecutable) + { + memory->offset = address; + memory->memory = NULL; + return CM_OK; + } + + // Error log in elfhandle by previous call will be check in loadTemplate + return ELF64_getRelocationMemory(elfhandle, elftmp, + (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader, + memory); +} + +/* + * Interface Management + */ +static t_interface_description* interfaceList = NULL; + +static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *elftmp, t_elf_interface_description* elfitf) { + t_dup_char itfType; + t_interface_description* itf; + int i; + + itfType = copyElfString(elftmp, elfitf->type); + if(itfType == NULL) + return NULL; + + // Search if interfane already loaded + for(itf = interfaceList; itf != NULL; itf = itf->next) { + if(itf->type == itfType) { + if (itf->methodNumber != elfitf->methodNumber) { + ERROR("When loading component template %s:\n\tNumber of methods in interface type %s\n\tdiffers from previous declaration: was %d, found %d\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), itfType, itf->methodNumber, elfitf->methodNumber, 0, 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + if (cmIntensiveCheckState) { + for(i = 0; i < itf->methodNumber; i++) { + if (cm_StringCompare(itf->methodNames[i], getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), MAX_INTERNAL_STRING_LENGTH) != 0) { + ERROR("When loading component template %s:\n" + "\tName of method number %d in interface type %s\n" + "\tdiffers from previous declaration: previous name was %s, new name found is %s\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), i, + itfType, itf->methodNames[i], + getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + } + } + itf->referenceCounter++; + cm_StringRelease(itfType); + return itf; + } + } + + // Create a new interface if not exists + itf = (t_interface_description*)OSAL_Alloc_Zero(sizeof(t_interface_description) + sizeof(t_dup_char) * (elfitf->methodNumber - 1)); + if(itf == NULL) + goto out_itf_type; + itf->referenceCounter = 1; + itf->type = itfType; + itf->methodNumber = elfitf->methodNumber; + for(i = 0; i < itf->methodNumber; i++) { + itf->methodNames[i] = copyElfString(elftmp, elfitf->methodNames[i]); + if(itf->methodNames[i] == NULL) + goto out_method; + } + + // Put it in Top + itf->next = interfaceList; + interfaceList = itf; + + return itf; + +out_method: + for(i = 0; i < itf->methodNumber; i++) + cm_StringRelease(itf->methodNames[i]); + OSAL_Free(itf); +out_itf_type: + cm_StringRelease(itfType); + return NULL; +} + +static void releaseInterfaceDescription(t_interface_description* itf) { + if(itf == NULL) + return; + + if(--itf->referenceCounter == 0) { + int i; + + // Remove it from list + if(interfaceList == itf) { + interfaceList = interfaceList->next; + } else { + t_interface_description* prev = interfaceList; + while(prev->next != itf) + prev = prev->next; + prev->next = itf->next; + } + + // Destroy interface description + for(i = 0; i < itf->methodNumber; i++) { + cm_StringRelease(itf->methodNames[i]); + } + cm_StringRelease(itf->type); + OSAL_Free(itf); + } +} + + +t_cm_error cm_ELF_CheckFile( + const char *elfdata, + t_bool temporaryDescription, + t_elfdescription **elfhandlePtr) +{ + t_elfdescription *elfhandle; + t_tmp_elfdescription elftmp; + t_cm_error error; + t_uint32 version; + t_uint32 compatibleVersion; + int i, j, k; + + /* + * Sanity check + */ + if (elfdata[EI_MAG0] != ELFMAG0 || + elfdata[EI_MAG1] != ELFMAG1 || + elfdata[EI_MAG2] != ELFMAG2 || + elfdata[EI_MAG3] != ELFMAG3 || + elfdata[EI_CLASS] != ELFCLASS64) + { + ERROR("CM_INVALID_ELF_FILE: component file is not a MMDSP ELF file\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + + /* + * Create elf data + */ + if((error = ELF64_LoadComponent(EM_MMDSP_PLUS, elfdata, elfhandlePtr, &elftmp)) != CM_OK) + return error; + + elfhandle = *elfhandlePtr; + + elfhandle->temporaryDescription = temporaryDescription; + + version = swap32(elftmp.elfheader->nmfVersion); + + compatibleVersion = (VERSION_MAJOR(version) == VERSION_MAJOR(NMF_VERSION)); + if(compatibleVersion) + { + switch(VERSION_MINOR(NMF_VERSION)) + { + case 10: // Compatible with 2.9, 2.10 + compatibleVersion = + (VERSION_MINOR(version) == 9) || + (VERSION_MINOR(version) == 10); + break; + default: // Strict compatibility 2.x == 2.x + compatibleVersion = (VERSION_MINOR(version) == VERSION_MINOR(NMF_VERSION)); + } + } + + if(! compatibleVersion) + { + ERROR("CM_INVALID_ELF_FILE: incompatible version for Component %d.%d.x != CM:%d.%d.x\n", + VERSION_MAJOR(version), VERSION_MINOR(version), + VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), 0, 0); + error = CM_INVALID_ELF_FILE; + goto onerror; + } + + + /* + * Commented since to many noise !!!! + if(VERSION_PATCH(version) != VERSION_PATCH(NMF_VERSION)) + { + WARNING("CM_INVALID_ELF_FILE: incompatible version, Component:%d.%d.%d != CM:%d.%d.%d\n", + VERSION_MAJOR(version), VERSION_MINOR(version), VERSION_PATCH(version), + VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), VERSION_PATCH(NMF_VERSION)); + } + */ + + if((error = ELF64_ComputeSegment(elfhandle, &elftmp)) != CM_OK) + goto onerror; + + // + elfhandle->foundedTemplateName = copyElfString(&elftmp, elftmp.elfheader->templateName); + if(elfhandle->foundedTemplateName == NULL) + goto oom; + elfhandle->minStackSize = swap32(elftmp.elfheader->minStackSize); + + // Get Life-cycle memory + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCConstruct, &elfhandle->memoryForConstruct)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStart, &elfhandle->memoryForStart)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStop, &elfhandle->memoryForStop)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCDestroy, &elfhandle->memoryForDestroy)) != CM_OK) + goto onerror; + + // Copy attributes information + elfhandle->attributeNumber = swap32(elftmp.elfheader->attributeNumber); + if(elfhandle->attributeNumber > 0) + { + elfhandle->attributes = + (t_attribute*)OSAL_Alloc_Zero(sizeof(t_attribute) * elfhandle->attributeNumber); + if(elfhandle->attributes == NULL) + goto oom; + + if(elfhandle->attributeNumber > 0) + { + t_elf_attribute *attributes = (t_elf_attribute*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->attributes); + + for(i = 0; i < elfhandle->attributeNumber; i++) + { + elfhandle->attributes[i].name = copyElfString(&elftmp, attributes[i].name); + if(elfhandle->attributes[i].name == NULL) + goto oom; + + if((error = getMemoryOffset(elfhandle, &elftmp, + MEM_DATA, + &attributes[i].symbols, + &elfhandle->attributes[i].memory)) != CM_OK) + goto onerror; + LOG_INTERNAL(2, " attribute %s mem=%s offset=%x\n", + elfhandle->attributes[i].name, + elfhandle->attributes[i].memory.memory->memoryName, + elfhandle->attributes[i].memory.offset, + 0, 0, 0); + } + } + } + + // Copy properties information + elfhandle->propertyNumber = swap32(elftmp.elfheader->propertyNumber); + if(elfhandle->propertyNumber > 0) + { + elfhandle->properties = + (t_property*)OSAL_Alloc_Zero(sizeof(t_property) * elfhandle->propertyNumber); + if(elfhandle->properties == NULL) + goto oom; + + if(elfhandle->propertyNumber > 0) + { + t_elf_property *properties = (t_elf_property*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->properties); + + for(i = 0; i < elfhandle->propertyNumber; i++) + { + elfhandle->properties[i].name = copyElfString(&elftmp, properties[i].name); + if(elfhandle->properties[i].name == NULL) + goto oom; + + elfhandle->properties[i].value = copyElfString(&elftmp, properties[i].value); + if(elfhandle->properties[i].value == NULL) + goto oom; + + LOG_INTERNAL(3, " property %s = %s\n", + elfhandle->properties[i].name, + elfhandle->properties[i].value, + 0, 0, 0, 0); + } + } + } + + // Copy requires information + elfhandle->requireNumber = swap32(elftmp.elfheader->requireNumber); + if(elfhandle->requireNumber > 0) + { + char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->requires); + + elfhandle->requires = (t_interface_require*)OSAL_Alloc_Zero(sizeof(t_interface_require) * elfhandle->requireNumber); + if(elfhandle->requires == NULL) + goto oom; + + for(i = 0; i < elfhandle->requireNumber; i++) + { + t_elf_required_interface *require = (t_elf_required_interface*)ref; + t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)require->interface); + + elfhandle->requires[i].name = copyElfString(&elftmp, require->name); + if(elfhandle->requires[i].name == NULL) + goto oom; + + elfhandle->requires[i].requireTypes = require->requireTypes; + elfhandle->requires[i].collectionSize = require->collectionSize; + elfhandle->requires[i].interface = getInterfaceDescription(&elftmp, interface); + if(elfhandle->requires[i].interface == NULL) + goto oom; + + LOG_INTERNAL(2, " require %s <%s> %x\n", + elfhandle->requires[i].name, + elfhandle->requires[i].interface->type, + elfhandle->requires[i].requireTypes, 0, 0, 0); + CM_ASSERT(elfhandle->requires[i].collectionSize != 0); + + ref = (char*)&require->indexes[0]; + + if((elfhandle->requires[i].requireTypes & VIRTUAL_REQUIRE) == 0 && + (elfhandle->requires[i].requireTypes & STATIC_REQUIRE) == 0) + { + elfhandle->requires[i].indexes = + (t_interface_require_index*)OSAL_Alloc_Zero(sizeof(t_interface_require_index) * elfhandle->requires[i].collectionSize); + if(elfhandle->requires[i].indexes == NULL) + goto oom; + + for(j = 0; j < elfhandle->requires[i].collectionSize; j++) + { + t_elf_interface_require_index* index = (t_elf_interface_require_index*)ref; + + elfhandle->requires[i].indexes[j].numberOfClient = swap32(index->numberOfClient); + if(elfhandle->requires[i].indexes[j].numberOfClient != 0) + { + elfhandle->requires[i].indexes[j].memories = + (t_memory_reference*)OSAL_Alloc(sizeof(t_memory_reference) * elfhandle->requires[i].indexes[j].numberOfClient); + if(elfhandle->requires[i].indexes[j].memories == NULL) + goto oom; + + for(k = 0; k < elfhandle->requires[i].indexes[j].numberOfClient; k++) { + if((error = getMemoryOffset(elfhandle,&elftmp, + MEM_DATA, + &index->symbols[k], + &elfhandle->requires[i].indexes[j].memories[k])) != CM_OK) + goto onerror; + LOG_INTERNAL(2, " [%d, %d] mem=%s offset=%x\n", + j, k, + elfhandle->requires[i].indexes[j].memories[k].memory->memoryName, + elfhandle->requires[i].indexes[j].memories[k].offset, + 0, 0); + } + } + + ref += sizeof(index->numberOfClient) + elfhandle->requires[i].indexes[j].numberOfClient * sizeof(index->symbols[0]); + } + } + } + } + + // Copy provides informations + elfhandle->provideNumber = swap32(elftmp.elfheader->provideNumber); + if(elfhandle->provideNumber != 0) + { + elfhandle->provides = + (t_interface_provide*)OSAL_Alloc_Zero(sizeof(t_interface_provide) * elfhandle->provideNumber); + if(elfhandle->provides == NULL) + goto oom; + + if(elfhandle->provideNumber > 0) + { + char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->provides); + + for(i = 0; i < elfhandle->provideNumber; i++) + { + t_elf_provided_interface *provide = (t_elf_provided_interface*)ref; + t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)provide->interface); + + elfhandle->provides[i].name = copyElfString(&elftmp, provide->name); + if(elfhandle->provides[i].name == NULL) + goto oom; + + elfhandle->provides[i].provideTypes = provide->provideTypes; + elfhandle->provides[i].interruptLine = provide->interruptLine; + elfhandle->provides[i].collectionSize = provide->collectionSize; + elfhandle->provides[i].interface = getInterfaceDescription(&elftmp, interface); + if(elfhandle->provides[i].interface == NULL) + goto oom; + + LOG_INTERNAL(2, " provide %s <%s>\n", + elfhandle->provides[i].name, + elfhandle->provides[i].interface->type, + 0,0, 0, 0); + CM_ASSERT(elfhandle->provides[i].collectionSize != 0); + + ref = (char*)&provide->methodSymbols[0]; + + { + t_uint32 *methodSymbols = (t_uint32*)ref; + + elfhandle->provides[i].indexes = (t_interface_provide_index**)OSAL_Alloc_Zero( + sizeof(t_interface_provide_index*) * elfhandle->provides[i].collectionSize); + if(elfhandle->provides[i].indexes == NULL) + goto oom; + + if(elfhandle->provides[i].interface->methodNumber != 0) + { + for(j = 0; j < elfhandle->provides[i].collectionSize; j++) + { + elfhandle->provides[i].indexes[j] = (t_interface_provide_index*)OSAL_Alloc( + sizeof(t_interface_provide_index) * elfhandle->provides[i].interface->methodNumber); + if(elfhandle->provides[i].indexes[j] == NULL) + goto oom; + + for(k = 0; k < elfhandle->provides[i].interface->methodNumber; k++) + { + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, + methodSymbols++, + &elfhandle->provides[i].indexes[j][k].memory)) != CM_OK) + goto onerror; + + if(elfhandle->provides[i].indexes[j][k].memory.memory != NULL) + LOG_INTERNAL(2, " [%d, %d] method '%s' mem=%s offset=%x\n", + j, k, + elfhandle->provides[i].interface->methodNames[k], + elfhandle->provides[i].indexes[j][k].memory.memory->memoryName, + elfhandle->provides[i].indexes[j][k].memory.offset, + 0); + else + LOG_INTERNAL(2, " [%d, %d] method '%s' address=%x\n", + j, k, + elfhandle->provides[i].interface->methodNames[k], + elfhandle->provides[i].indexes[j][k].memory.offset, + 0, 0); + } + } + } + + ref += elfhandle->provides[i].collectionSize * elfhandle->provides[i].interface->methodNumber * sizeof(methodSymbols[0]); + } + } + } + } + + return CM_OK; + +oom: + error = CM_NO_MORE_MEMORY; +onerror: + cm_ELF_CloseFile(temporaryDescription, elfhandle); + *elfhandlePtr = NULL; + return error; +} + +void cm_ELF_ReleaseDescription( + t_uint32 requireNumber, t_interface_require *requires, + t_uint32 attributeNumber, t_attribute *attributes, + t_uint32 propertyNumber, t_property *properties, + t_uint32 provideNumber, t_interface_provide *provides) +{ + int i, j; + + // Free provides (Number set when array allocated) + if(provides != NULL) + { + for(i = 0; i < provideNumber; i++) + { + if(provides[i].indexes != NULL) + { + for(j = 0; j < provides[i].collectionSize; j++) + { + OSAL_Free(provides[i].indexes[j]); + } + OSAL_Free(provides[i].indexes); + } + releaseInterfaceDescription(provides[i].interface); + cm_StringRelease(provides[i].name); + } + OSAL_Free(provides); + } + + // Free requires (Number set when array allocated) + if(requires != NULL) + { + for(i = 0; i < requireNumber; i++) + { + if(requires[i].indexes != 0) + { + for(j = 0; j < requires[i].collectionSize; j++) + { + OSAL_Free(requires[i].indexes[j].memories); + } + OSAL_Free(requires[i].indexes); + } + releaseInterfaceDescription(requires[i].interface); + cm_StringRelease(requires[i].name); + } + OSAL_Free(requires); + } + + // Free properties (Number set when array allocated) + if(properties != NULL) + { + for(i = 0; i < propertyNumber; i++) + { + cm_StringRelease(properties[i].value); + cm_StringRelease(properties[i].name); + } + OSAL_Free(properties); + } + + // Free Attributes (Number set when array allocated) + if(attributes != NULL) + { + for(i = 0; i < attributeNumber; i++) + { + cm_StringRelease(attributes[i].name); + } + OSAL_Free(attributes); + } +} + +void cm_ELF_CloseFile( + t_bool temporaryDescription, + t_elfdescription *elfhandle) +{ + if(elfhandle == NULL) + return; + + if(temporaryDescription && ! elfhandle->temporaryDescription) + return; + + // Release description if not moved to template + cm_ELF_ReleaseDescription( + elfhandle->requireNumber, elfhandle->requires, + elfhandle->attributeNumber, elfhandle->attributes, + elfhandle->propertyNumber, elfhandle->properties, + elfhandle->provideNumber, elfhandle->provides); + + cm_StringRelease(elfhandle->foundedTemplateName); + + ELF64_UnloadComponent(elfhandle); +} + + +static t_cm_error allocSegment( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY], + t_memory_property property, + t_bool isSingleton) { + t_memory_id memId; + const t_elfmemory *thisMemory; //!< Memory used to determine this + const t_elfmemory *codeMemory; //!< Memory used to determine code + + MMDSP_serializeMemories(elfhandle->instanceProperty, &codeMemory, &thisMemory); + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + const t_elfmemory* mapping; + + if(elfhandle->segments[memId].sumSize == 0x0) + continue; + + mapping = MMDSP_getMappingById(memId); + + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + // Allocate segment + memories[memId] = cm_DM_Alloc(domainId, mapping->dspMemType, + elfhandle->segments[memId].sumSize / mapping->fileEntSize, + mapping->memAlignement, TRUE); + + if(memories[memId] == INVALID_MEMORY_HANDLE) + { + ERROR("CM_NO_MORE_MEMORY(%s): %x too big\n", mapping->memoryName, elfhandle->segments[memId].sumSize / mapping->fileEntSize, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + // Get reference in memory + elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]); + + cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr); + + if (isSingleton) + cm_DM_SetDefaultDomain(memories[memId], cm_DM_GetDomainCoreId(domainId)); + + // Log it + LOG_INTERNAL(1, "\t%s%s: 0x%x..+0x%x (0x%x)\n", + mapping->memoryName, + (thisMemory == mapping) ? "(THIS)" : "", + elfhandle->segments[memId].mpcAddr, + elfhandle->segments[memId].sumSize / mapping->fileEntSize, + elfhandle->segments[memId].hostAddr, 0); + } + else if(property == MEM_PRIVATE) // Since we allocate private segment, if not allocate, it's a share one + { + // In order to allow further relocation based on cached address like mpcAddr & hostAddr, + // initialize them also ! + + // Get reference in memory + elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]); + + cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr); + } + } + + return CM_OK; +} + +/* + * Note: in case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeTemplate + */ +t_cm_error cm_ELF_LoadTemplate( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton) +{ + t_cm_error error; + + if((error = allocSegment(domainId, elfhandle, sharedMemories, MEM_SHARABLE, isSingleton)) != CM_OK) + return error; + + // Load each readonly segment + if((error = ELF64_loadSegment(elfhandle, sharedMemories, MEM_SHARABLE)) != CM_OK) + return error; + + return CM_OK; +} + +t_cm_error cm_ELF_LoadInstance( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton) +{ + t_memory_id memId; + t_cm_error error; + + // Erase whole memories to make free in case of error + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + privateMemories[memId] = sharedMemories[memId]; + } + + if((error = allocSegment(domainId, elfhandle, privateMemories, MEM_PRIVATE, isSingleton)) != CM_OK) + return error; + + // Load each writable memory + if((error = ELF64_loadSegment(elfhandle, privateMemories, MEM_PRIVATE)) != CM_OK) + return error; + + return CM_OK; +} + +void cm_ELF_FlushTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(sharedMemories[memId] != INVALID_MEMORY_HANDLE) + MMDSP_loadedSection( + coreId, memId, + sharedMemories[memId]); + } +} + +void cm_ELF_FlushInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId]) + MMDSP_loadedSection( + coreId, memId, + privateMemories[memId]); + } +} + +void cm_ELF_FreeInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + if(privateMemories == NULL) + return; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId]) + { + MMDSP_unloadedSection(coreId, memId, privateMemories[memId]); + cm_DM_Free(privateMemories[memId], TRUE); + } + } +} + +void cm_ELF_FreeTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + if(sharedMemories == NULL) + return; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(sharedMemories[memId] != INVALID_MEMORY_HANDLE) + { + MMDSP_unloadedSection(coreId, memId, sharedMemories[memId]); + cm_DM_Free(sharedMemories[memId], TRUE); + } + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c new file mode 100644 index 00000000000..5f6641b188d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include <cm/engine/elf/inc/mmdsp.h> +#include <cm/engine/elf/inc/bfd.h> +#include <cm/engine/elf/inc/mpcal.h> + +#include <cm/engine/component/inc/initializer.h> + +#include <cm/engine/utils/inc/string.h> +#include <cm/engine/utils/inc/swap.h> +#include <cm/engine/trace/inc/trace.h> + +#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h> + +static const t_elfmemory mmdspMemories[NUMBER_OF_MMDSP_MEMORY] = { + {0, SDRAM_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "SDRAM_CODE"}, /* 0: Program memory */ + {1, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "XROM"}, /* 1: Internal X memory */ + {2, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "YROM"}, /* 2: Y memory */ + {3, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "SDR0M24"}, /* 5: SDRAM24 */ + {4, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "SDROM16"}, /* 6: SDRAM16 */ + {5, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "ESROM24"}, /* 8: ESRAM24 */ + {6, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "ESROM16"}, /* 9: ESRAM16 */ + {7, ESRAM_CODE, ESRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "ESRAM_CODE"}, /*10: ESRAM code */ + {8, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "XRAM"}, /* 1: Internal X memory */ + {9, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "YRAM"}, /* 2: Y memory */ + {10, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "SDRAM24"}, /* 5: SDRAM24 */ + {11, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "SDRAM16"}, /* 6: SDRAM16 */ + {12, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "ESRAM24"}, /* 8: ESRAM24 */ + {13, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "ESRAM16"}, /* 9: ESRAM16 */ + {14, LOCKED_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "LOCKED_CODE"}, /* : .locked */ +}; + +#define MAX_ELFSECTIONNAME 10 +struct memoryMapping { + char *elfSectionName; + t_uint32 memoryIndex[MEM_FOR_LAST]; // memoryIndex[t_instance_property] +}; + +static const struct memoryMapping mappingmem0[] = { + {"mem0.0", {0, 0}}, + {"mem0.1", {0, 0}}, + {"mem0.2", {0, 0}} +}; +static const struct memoryMapping mappingmem10 = + {"mem10", {7, 7}}; +static const struct memoryMapping mappinglocked = + {".locked", {14, 14}}; +static const struct memoryMapping mappingmem1[] = { + {"", {0xff, 0xff}}, + {"mem1.1", {1, 1}}, + {"mem1.2", {8, 1}}, + {"mem1.3", {1, 1}}, + {"mem1.4", {8, 1}}, + {"mem1.stack", {8, 1}} +}; +static const struct memoryMapping mappingmem2[] = { + {"", {0xff, 0xff}}, + {"mem2.1", {2, 2}}, + {"mem2.2", {9, 2}}, + {"mem2.3", {2, 2}}, + {"mem2.4", {9, 2}} +}; +static const struct memoryMapping mappingmem5[] = { + {"", {0xff, 0xff}}, + {"mem5.1", {3, 3}}, + {"mem5.2", {10, 3}}, + {"mem5.3", {3, 3}}, + {"mem5.4", {10, 3}} +}; +static const struct memoryMapping mappingmem6[] = { + {"", {0xff, 0xff}}, + {"mem6.1", {4, 4}}, + {"mem6.2", {11, 4}}, + {"mem6.3", {4, 4}}, + {"mem6.4", {11, 4}} +}; +static const struct memoryMapping mappingmem8[] = { + {"", {0xff, 0xff}}, + {"mem8.1", {5, 5}}, + {"mem8.2", {12, 5}}, + {"mem8.3", {5, 5}}, + {"mem8.4", {12, 5}} +}; +static const struct memoryMapping mappingmem9[] = { + {"", {0xff, 0xff}}, + {"mem9.1", {6, 6}}, + {"mem9.2", {13, 6}}, + {"mem9.3", {6, 6}}, + {"mem9.4", {13, 6}} +}; + +static const struct { + const struct memoryMapping* mapping; + unsigned int number; +} hashMappings[10] = { + {mappingmem0, sizeof(mappingmem0) / sizeof(mappingmem0[0])}, + {mappingmem1, sizeof(mappingmem1) / sizeof(mappingmem1[0])}, + {mappingmem2, sizeof(mappingmem2) / sizeof(mappingmem2[0])}, + {0x0, 0}, + {0x0, 0}, + {mappingmem5, sizeof(mappingmem5) / sizeof(mappingmem5[0])}, + {mappingmem6, sizeof(mappingmem6) / sizeof(mappingmem6[0])}, + {0x0, 0}, + {mappingmem8, sizeof(mappingmem8) / sizeof(mappingmem8[0])}, + {mappingmem9, sizeof(mappingmem9) / sizeof(mappingmem9[0])}, +}; + +const t_elfmemory* MMDSP_getMappingById(t_memory_id memId) +{ + return &mmdspMemories[memId]; +} + +const t_elfmemory* MMDSP_getMappingByName(const char* sectionName, t_instance_property property) +{ + if(sectionName[0] == 'm' && sectionName[1] == 'e' && sectionName[2] == 'm') + { + if(sectionName[4] == '.') + { + if(sectionName[5] >= '0' && sectionName[5] <= '9') + { + if(sectionName[3] >= '0' && sectionName[3] <= '9') + { + unsigned int m, sm; + + m = sectionName[3] - '0'; + sm = sectionName[5] - '0'; + if(sm < hashMappings[m].number) + return &mmdspMemories[hashMappings[m].mapping[sm].memoryIndex[property]]; + } + } else if(sectionName[3] == '1' && sectionName[5] == 's') + return &mmdspMemories[mappingmem1[5].memoryIndex[property]]; + } + else if(sectionName[3] == '1' && sectionName[4] == '0') + return &mmdspMemories[mappingmem10.memoryIndex[property]]; + } + else if(sectionName[0] == '.' && sectionName[1] == 'l' && sectionName[2] == 'o' && sectionName[3] == 'c' && + sectionName[4] == 'k' && sectionName[5] == 'e' && sectionName[6] == 'd') + { + return &mmdspMemories[mappinglocked.memoryIndex[property]]; + } + + return NULL; +} + +void MMDSP_serializeMemories(t_instance_property property, + const t_elfmemory** codeMemory, const t_elfmemory** thisMemory) { + // Return meory reference + *codeMemory = &mmdspMemories[0]; + if(property == MEM_FOR_SINGLETON) + { + *thisMemory = &mmdspMemories[1]; + } + else + { + *thisMemory = &mmdspMemories[8]; + } +} + +void MMDSP_copyCode(t_uint64 * remoteAddr64, const char* origAddr, int nb) +{ + int m; + + // Linux allow unaligned access +#ifdef LINUX + t_uint64 *origAddr64 = (t_uint64*)origAddr; +#else + __packed t_uint64 *origAddr64 = (__packed t_uint64*)origAddr; +#endif + + for (m = 0; m < nb; m += 8) + { + *remoteAddr64++ = swap64(*origAddr64++); + } +} + +void MMDSP_copyData24(t_uint32 * remoteAddr32, const char* origAddr, int nb) +{ + int m; + + for (m = 0; m < nb; m+=4) + { + t_uint32 value1; + + value1 = (*origAddr++ << 16); + value1 |= (*origAddr++ << 8); + value1 |= (*origAddr++ << 0); + *remoteAddr32++ = value1; + } +} + +void MMDSP_copyData16(t_uint16 * remoteAddr16, const char* origAddr, int nb) +{ + int m; + + for (m = 0; m < nb; m+=2) + { + t_uint16 value1; + + origAddr++; // Skip this byte (which is put in elf file for historical reason) + value1 = (*origAddr++ << 8); + value1 |= (*origAddr++ << 0); + *remoteAddr16++ = value1; + } +} + +#if 0 +__asm void MMDSP_copyCode(void* dst, const void* src, int nb) +{ + PUSH {r4-r8, lr} + SUBS r2,r2,#0x20 + BCC l4 + +l5 + SETEND BE + LDR r4, [r1], #0x4 + LDR r3, [r1], #0x4 + LDR r6, [r1], #0x4 + LDR r5, [r1], #0x4 + LDR r8, [r1], #0x4 + LDR r7, [r1], #0x4 + LDR lr, [r1], #0x4 + LDR r12, [r1], #0x4 + + SETEND LE + STM r0!,{r3-r8,r12, lr} + SUBS r2,r2,#0x20 + BCS l5 + +l4 + LSLS r12,r2,#28 + + SETEND BE + LDRCS r4, [r1], #0x4 + LDRCS r3, [r1], #0x4 + LDRCS r6, [r1], #0x4 + LDRCS r5, [r1], #0x4 + SETEND LE + STMCS r0!,{r3-r6} + + SETEND BE + LDRMI r4, [r1], #0x4 + LDRMI r3, [r1], #0x4 + SETEND LE + STMMI r0!,{r3-r4} + + POP {r4-r8, pc} +} +#endif + +#ifdef LINUX +static void PLD5(int r) +{ + asm volatile ( + "PLD [r0, #0x20] \n\t" + "PLD [r0, #0x40] \n\t" + "PLD [r0, #0x60] \n\t" + "PLD [r0, #0x80] \n\t" + "PLD [r0, #0xA0]" ); +} + +static void PLD1(int r) +{ + asm volatile ( + "PLD [r0, #0xC0]" ); +} +#else /* Symbian, Think -> We assume ARMCC */ +static __asm void PLD5(int r) +{ + PLD [r0, #0x20] + PLD [r0, #0x40] + PLD [r0, #0x60] + PLD [r0, #0x80] + PLD [r0, #0xA0] + + bx lr +} + +static __asm void PLD1(int r) +{ + PLD [r0, #0xC0] + + bx lr +} +#endif + +#if 0 +__asm void COPY(void* dst, const void* src, int nb) +{ + PUSH {r4-r8, lr} + SUBS r2,r2,#0x20 + BCC l4a + PLD [r1, #0x20] + PLD [r1, #0x40] + PLD [r1, #0x60] + PLD [r1, #0x80] + PLD [r1, #0xA0] + +l5a + PLD [r1, #0xC0] + LDM r1!,{r3-r8,r12,lr} + STM r0!,{r3-r8,r12,lr} + SUBS r2,r2,#0x20 + BCS l5a + +l4a + LSLS r12,r2,#28 + LDMCS r1!,{r3,r4,r12,lr} + STMCS r0!,{r3,r4,r12,lr} + LDMMI r1!,{r3,r4} + STMMI r0!,{r3,r4} + POP {r4-r8,lr} + LSLS r12,r2,#30 + LDRCS r3,[r1],#4 + STRCS r3,[r0],#4 + BXEQ lr +l6b + LSLS r2,r2,#31 + LDRHCS r3,[r1],#2 + LDRBMI r2,[r1],#1 + STRHCS r3,[r0],#2 + STRBMI r2,[r0],#1 + BX lr +} +#endif + + +void MMDSP_copySection(t_uint32 origAddr, t_uint32 remoteAddr, t_uint32 sizeInByte) { + t_uint32 endAddr = remoteAddr + sizeInByte; + + PLD5(origAddr); + + // Align on 32bits + if((remoteAddr & 0x3) != 0) + { + *(t_uint16*)remoteAddr = *(t_uint16*)origAddr; + remoteAddr += sizeof(t_uint16); + origAddr += sizeof(t_uint16); + } + + // Align on 64bits + if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32))) + { + *(t_uint32*)remoteAddr = *(t_uint32*)origAddr; + remoteAddr += sizeof(t_uint32); + origAddr += sizeof(t_uint32); + } + + // 64bits burst access + for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64), origAddr += sizeof(t_uint64)) + { + PLD1(origAddr); + *(volatile t_uint64*)remoteAddr = *(t_uint64*)origAddr; + } + + // Remain 32bits access + if(remoteAddr <= endAddr - sizeof(t_uint32)) + { + *(t_uint32*)remoteAddr = *(t_uint32*)origAddr; + remoteAddr += sizeof(t_uint32); + origAddr += sizeof(t_uint32); + } + + // Remain 16bits access + if(remoteAddr <= endAddr - sizeof(t_uint16)) + *(t_uint16*)remoteAddr = *(t_uint16*)origAddr; +} + + +void MMDSP_bzeroSection(t_uint32 remoteAddr, t_uint32 sizeInByte) { + t_uint32 endAddr = remoteAddr + sizeInByte; + + // Align on 32bits + if((remoteAddr & 0x3) != 0) + { + *(t_uint16*)remoteAddr = 0; + remoteAddr += sizeof(t_uint16); + } + + // Align on 64bits + if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32))) + { + *(t_uint32*)remoteAddr = 0; + remoteAddr += sizeof(t_uint32); + } + + // 64bits burst access + for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64)) + *(volatile t_uint64*)remoteAddr = 0ULL; + + // Remain 32bits access + if(remoteAddr <= endAddr - sizeof(t_uint32)) + { + *(t_uint32*)remoteAddr = 0; + remoteAddr += sizeof(t_uint32); + } + + // Remain 16bits access + if(remoteAddr <= endAddr - sizeof(t_uint16)) + *(t_uint16*)remoteAddr = 0; +} + +void MMDSP_loadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle) +{ + if(mmdspMemories[memId].purpose == MEM_CODE) + { + OSAL_CleanDCache(cm_DSP_GetHostLogicalAddress(handle), cm_MM_GetSize(handle)); + } + + if(memId == LOCKED_CODE) + { + t_uint32 DspAddress, DspSize; + + cm_DSP_GetDspMemoryHandleSize(handle, &DspSize); + cm_DSP_GetDspAddress(handle, &DspAddress); + + cm_COMP_InstructionCacheLock(coreId, DspAddress, DspSize); + } +} + +void MMDSP_unloadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle) +{ + if(memId == LOCKED_CODE) + { + t_uint32 DspAddress, DspSize; + + cm_DSP_GetDspMemoryHandleSize(handle, &DspSize); + cm_DSP_GetDspAddress(handle, &DspAddress); + + cm_COMP_InstructionCacheUnlock(coreId, DspAddress, DspSize); + } + +} + +static struct reloc_howto_struct elf64_mmdsp_howto_table[] = +{ + HOWTO (R_MMDSP_IMM20_16, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 8, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM20_16", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0000000000ffff00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 4-bit absolute relocation for splitted 20 bits immediate, shifted by 56 */ + + HOWTO (R_MMDSP_IMM20_4, /* type */ + 16, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* bitsize */ + FALSE, /* pc_relative */ + 56, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM20_4", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0f00000000000000LL, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MMDSP_24, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_24", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MMDSP_IMM16, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 8, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM16", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0000000000ffff00, /* dst_mask */ + FALSE), /* pcrel_offset */ +}; + +static const char* lastInPlaceAddr = 0; +static long long lastInPlaceValue; + +void MMDSP_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr, + const char* inPlaceAddr, + t_uint32 reloc_offset) { + int i; + + for(i = 0; i < sizeof(elf64_mmdsp_howto_table) / sizeof(elf64_mmdsp_howto_table[0]); i++) + { + struct reloc_howto_struct* howto = &elf64_mmdsp_howto_table[i]; + if(howto->type == type) + { + t_uint64 relocation; + + LOG_INTERNAL(2, "reloc '%s:0x%x' type %s at 0x%x (0x%x)\n", + symbol_name ? symbol_name : "??", symbol_addr, + howto->name, + reloc_offset, reloc_addr, 0); + + relocation = symbol_addr; + + if (howto->pc_relative) { + // Not handle yet + } + + if (howto->complain_on_overflow != complain_overflow_dont) { + // Not handle yet + } + + relocation >>= howto->rightshift; + + relocation <<= howto->bitpos; + +#define DOIT(x) \ + x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) + + switch (howto->size) { + case 2: { + long x = *(long*)inPlaceAddr; + + // CM_ASSERT(*(long*)inPlaceAddr == *(long*)reloc_addr); + + DOIT (x); + *(long*)reloc_addr = x; + } + break; + case 4: { + long long x; + if(lastInPlaceAddr == inPlaceAddr) + { + x = lastInPlaceValue; + } + else + { + // CM_ASSERT(*(__packed long long*)inPlaceAddr == *(long long*)reloc_addr); + x = *(long long*)inPlaceAddr; + lastInPlaceAddr = inPlaceAddr; + } + + DOIT (x); + *(long long*)reloc_addr = lastInPlaceValue = x; + } + break; + default: + CM_ASSERT(0); + } + + return; + } + } + + ERROR("Relocation type %d not supported for '%s'\n", type, symbol_name, 0, 0, 0, 0); +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c new file mode 100644 index 00000000000..b08ac6a361e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include <cm/engine/elf/inc/bfd.h> +#include <cm/engine/elf/inc/mpcal.h> +#include <cm/engine/trace/inc/trace.h> +#include <cm/engine/utils/inc/string.h> + +t_cm_error cm_ELF_relocateSharedSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext) +{ + return ELF64_relocateSegments( + memories, + elfhandle, + MEM_SHARABLE, + cbContext); +} + +t_cm_error cm_ELF_relocatePrivateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext) +{ + return ELF64_relocateSegments( + memories, + elfhandle, + MEM_PRIVATE, + cbContext); +} + +void cm_ELF_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr) +{ + MMDSP_performRelocation( + type, + symbol_name, + symbol_addr, + reloc_addr, + reloc_addr, + 0xBEEF); + + OSAL_CleanDCache((t_uint32)reloc_addr, 8); +} + +t_cm_error cm_ELF_GetMemory( + t_elfdescription *elf, + t_tmp_elfdescription *elftmp, + t_uint32 address, + t_memory_purpose purpose, + t_memory_reference *memory) { + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + const t_elfmemory* mem = MMDSP_getMappingById(memId); + + if(mem->purpose == purpose && // Memory correspond + elf->segments[mem->id].sumSize != 0 && // Segment allocated + (elf->segments[mem->id].mpcAddr <= address) && + (address < elf->segments[mem->id].mpcAddr + elf->segments[mem->id].sumSize / mem->fileEntSize)) { + memory->memory = mem; + memory->offset = address - elf->segments[mem->id].mpcAddr; + return CM_OK; + } + } + + ERROR("Memory %x,%d not found\n", address, purpose, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c new file mode 100644 index 00000000000..4a2976a6bc1 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c @@ -0,0 +1,591 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include <cm/engine/elf/inc/mpcal.h> + +#include <cm/engine/utils/inc/string.h> +#include <cm/engine/utils/inc/mem.h> + + +static t_uint32 max(t_uint32 a, t_uint32 b) +{ + return (a >= b) ? a : b; +} +/* +static t_uint32 min(t_uint32 a, t_uint32 b) +{ + return (a <= b) ? a : b; +} +*/ + +struct XXrelocation +{ + t_uint32 st_value; + ElfXX_Half st_shndx; + Elf64_Sxword r_addend; + t_uint32 OffsetInElf; + t_uint32 type; + + t_dup_char symbol_name; // Valid only if st_shndx == SHN_UNDEF +}; + +struct XXSection { + ElfXX_Word sh_type; /* Section type */ + t_uint32 sh_size; /* Section size in bytes */ + ElfXX_Word sh_info; /* Additional section information */ + ElfXX_Word sh_link; /* Link to another section */ + t_uint32 sh_addralign; /* Some sections have address alignment constraints */ + t_uint32 sh_addr; /* Section addr */ + ElfXX_Xword sh_flags; /* Section flags */ + + const char *data; + t_uint32 trueDataSize; /* Valid if different from sh_size */ + const char *sectionName; + + t_uint32 offsetInSegment; + const t_elfmemory *meminfo; + + t_uint32 relocationNumber; + struct XXrelocation *relocations; +}; + +struct XXElf { + t_uint32 e_shnum; + struct XXSection sectionss[1]; +}; + +t_cm_error ELF64_LoadComponent( + t_uint16 e_machine, + const char *elfdata, + t_elfdescription **elfhandlePtr, + t_tmp_elfdescription *elftmp) +{ + t_elfdescription *elfhandle; + const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elfdata; + const ElfXX_Shdr *sections; + const char *strings; + struct XXElf* ELF; + int i, nb; + + elftmp->elfdata = elfdata; + + /* Sanity check */ + if (swapHalf(header->e_machine) != e_machine) + { + ERROR("This is not a executable for such MPC\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + + // Cache elf file informations + nb = swapHalf(header->e_shnum); + elftmp->isExecutable = (swapHalf(header->e_type) == ET_EXEC); + + elfhandle = (t_elfdescription*)OSAL_Alloc_Zero( + sizeof(t_elfdescription) + sizeof(struct XXElf) + sizeof(struct XXSection) * (nb - 1)); + if(elfhandle == NULL) + return CM_NO_MORE_MEMORY; + + ELF = elfhandle->ELF = (struct XXElf*)(elfhandle + 1); + + ELF->e_shnum = nb; + + sections = (ElfXX_Shdr*)&elfdata[swapXword(header->e_shoff)]; + // Compute and swap section infromation + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].sh_type = swapWord(sections[i].sh_type); + ELF->sectionss[i].sh_info = swapWord(sections[i].sh_info); + ELF->sectionss[i].sh_link = swapWord(sections[i].sh_link); + ELF->sectionss[i].sh_size = (t_uint32)swapXword(sections[i].sh_size); + ELF->sectionss[i].sh_addralign = (t_uint32)swapXword(sections[i].sh_addralign); + ELF->sectionss[i].sh_addr = (t_uint32)swapXword(sections[i].sh_addr); + ELF->sectionss[i].sh_flags = swapXword(sections[i].sh_flags); + + elftmp->sectionData[i] = &elfdata[(t_uint32)swapXword(sections[i].sh_offset)]; + } + + /* + * search nmf_segment + */ + strings = elftmp->sectionData[swapHalf(header->e_shstrndx)]; + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].sectionName = &strings[swapWord(sections[i].sh_name)]; + + // Found nmf_segment to see if it's + if(cm_StringCompare("nmf_segment", ELF->sectionss[i].sectionName, 11) == 0) { + elftmp->nmfSectionIndex = i; + elftmp->elfheader = (const t_elf_component_header*)elftmp->sectionData[i]; + } + } + + if(elftmp->nmfSectionIndex == 0) + { + ERROR("This is not a NMF component\n", 0, 0, 0, 0, 0, 0); + goto invalid; + } + + /* + * Determine component type + */ + elfhandle->magicNumber = swap32(elftmp->elfheader->magic); + switch(elfhandle->magicNumber) { + case MAGIC_COMPONENT: + elfhandle->instanceProperty = MEM_FOR_MULTIINSTANCE; + break; + case MAGIC_SINGLETON: + case MAGIC_FIRMWARE: + elfhandle->instanceProperty = MEM_FOR_SINGLETON; + break; + } + + // Copy content + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].meminfo = MMDSP_getMappingByName( + ELF->sectionss[i].sectionName, + elfhandle->instanceProperty); + + if(ELF->sectionss[i].meminfo != NULL) + ELF->sectionss[i].trueDataSize = (ELF->sectionss[i].sh_size / ELF->sectionss[i].meminfo->fileEntSize) * ELF->sectionss[i].meminfo->memEntSize; + + if(ELF->sectionss[i].sh_size != 0 && + ELF->sectionss[i].sh_type == SHT_PROGBITS && + (ELF->sectionss[i].sh_flags & SHF_ALLOC) != 0) + { + const char* elfAddr = elftmp->sectionData[i]; + + ELF->sectionss[i].data = OSAL_Alloc(ELF->sectionss[i].trueDataSize); + if(ELF->sectionss[i].data == NULL) + goto oom; + + if(ELF->sectionss[i].meminfo->purpose == MEM_CODE) + { + MMDSP_copyCode( + (t_uint64*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA && + // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 && + ELF->sectionss[i].meminfo->memEntSize == 4) + { + MMDSP_copyData24( + (t_uint32*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA && + // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 && + ELF->sectionss[i].meminfo->memEntSize == 2) + { + MMDSP_copyData16( + (t_uint16*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else + CM_ASSERT(0); + } + } + + // Copy relocation + // Loop on all relocation section + for(i=0; i < ELF->e_shnum; i++) + { + int sh_info; + + // Does this section is a relocation table (only RELA supported) + if((ELF->sectionss[i].sh_type != SHT_RELA) || + ELF->sectionss[i].sh_size == 0) continue; + + // Copy only relocation for loaded section + sh_info = ELF->sectionss[i].sh_info; + if(ELF->sectionss[sh_info].meminfo != NULL) + { + const ElfXX_Sym* symtab; + const char* strtab; + ElfXX_Rela* rel_start; + int n; + + ELF->sectionss[sh_info].relocationNumber = ELF->sectionss[i].sh_size / sizeof(ElfXX_Rela); + ELF->sectionss[sh_info].relocations = (struct XXrelocation*)OSAL_Alloc_Zero(sizeof(struct XXrelocation) * ELF->sectionss[sh_info].relocationNumber); + if(ELF->sectionss[sh_info].relocations == NULL) + goto oom; + + symtab = (ElfXX_Sym *)elftmp->sectionData[ELF->sectionss[i].sh_link]; + strtab = elftmp->sectionData[ELF->sectionss[ELF->sectionss[i].sh_link].sh_link]; + rel_start = (ElfXX_Rela*)elftmp->sectionData[i]; + for(n = 0; n < ELF->sectionss[sh_info].relocationNumber; n++, rel_start++) + { + struct XXrelocation* relocation = &ELF->sectionss[sh_info].relocations[n]; + ElfXX_Xword r_info = swapXword(rel_start->r_info); + int strtab_index = ELFXX_R_SYM(r_info); + const char* symbol_name = &strtab[swapWord(symtab[strtab_index].st_name)]; + + relocation->st_shndx = swapHalf(symtab[strtab_index].st_shndx); + relocation->st_value = (t_uint32)swapXword(symtab[strtab_index].st_value); + relocation->r_addend = swapXword(rel_start->r_addend); + relocation->OffsetInElf = (t_uint32)swapXword(rel_start->r_offset) / ELF->sectionss[sh_info].meminfo->fileEntSize; + relocation->type = ELFXX_R_TYPE(r_info); + + switch(relocation->st_shndx) { + case SHN_UNDEF: + relocation->symbol_name = cm_StringDuplicate(symbol_name + 1); /* Remove '_' prefix */ + if(relocation->symbol_name == NULL) + goto oom; + break; + case SHN_COMMON: + ERROR("SHN_COMMON not handle for %s\n", symbol_name, 0, 0, 0, 0, 0); + goto invalid; + } + } + } + } + + *elfhandlePtr = elfhandle; + return CM_OK; +invalid: + ELF64_UnloadComponent(elfhandle); + return CM_INVALID_ELF_FILE; +oom: + ELF64_UnloadComponent(elfhandle); + return CM_NO_MORE_MEMORY; +} + +t_cm_error ELF64_ComputeSegment( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp) +{ + struct XXElf* ELF = elfhandle->ELF; + int i; + + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].offsetInSegment = 0xFFFFFFFF; + + if(ELF->sectionss[i].sh_type == SHT_PROGBITS || ELF->sectionss[i].sh_type == SHT_NOBITS) { + // This is a loadable memory (memory size could be zero since we can have symbol on it)... + const t_elfmemory* meminfo = ELF->sectionss[i].meminfo; + + if(meminfo != NULL) { + // Which correspond to MPC memory + + if(elftmp->isExecutable) + { + if(! elfhandle->segments[meminfo->id].sumSizeSetted) + { + CM_ASSERT(ELF->sectionss[i].sh_addr >= meminfo->startAddr * meminfo->fileEntSize); + + elfhandle->segments[meminfo->id].sumSizeSetted = TRUE; + elfhandle->segments[meminfo->id].sumSize = ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize; + } + else + CM_ASSERT(elfhandle->segments[meminfo->id].sumSize == ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize); + } + else + { + while(elfhandle->segments[meminfo->id].sumSize % ELF->sectionss[i].sh_addralign != 0) + elfhandle->segments[meminfo->id].sumSize++; + } + + elfhandle->segments[meminfo->id].maxAlign = max(elfhandle->segments[meminfo->id].maxAlign, ELF->sectionss[i].sh_addralign); + ELF->sectionss[i].offsetInSegment = elfhandle->segments[meminfo->id].sumSize / meminfo->fileEntSize; + elfhandle->segments[meminfo->id].sumSize += ELF->sectionss[i].sh_size; + } + } else if(ELF->sectionss[i].sh_type == SHT_RELA && ELF->sectionss[i].sh_info == elftmp->nmfSectionIndex) { + int secsym = ELF->sectionss[i].sh_link; + elftmp->relaNmfSegment = (ElfXX_Rela*)elftmp->sectionData[i]; + elftmp->relaNmfSegmentEnd = (ElfXX_Rela*)((t_uint32)elftmp->relaNmfSegment + ELF->sectionss[i].sh_size); + elftmp->relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->sectionData[secsym]; + elftmp->relaNmfSegmentStrings = elftmp->sectionData[ELF->sectionss[secsym].sh_link]; + } + } + + return CM_OK; +} + +void ELF64_UnloadComponent( + t_elfdescription *elfhandle) +{ + struct XXElf* ELF = elfhandle->ELF; + int i, n; + + for(i = 0; i < ELF->e_shnum; i++) + { + if(ELF->sectionss[i].relocations != NULL) + { + for(n = 0; n < ELF->sectionss[i].relocationNumber; n++) + cm_StringRelease(ELF->sectionss[i].relocations[n].symbol_name); + OSAL_Free(ELF->sectionss[i].relocations); + } + + OSAL_Free((void*)ELF->sectionss[i].data); + } + OSAL_Free(elfhandle); +} + +t_cm_error ELF64_loadSegment( + t_elfdescription *elfhandle, + t_memory_handle *memory, + t_memory_property property) +{ + struct XXElf* ELF = elfhandle->ELF; + int i; + + /* + * Copy ELF data in this segment + */ + for(i = 0; i < ELF->e_shnum; i++) + { + const t_elfmemory* mapping = ELF->sectionss[i].meminfo; + + if(mapping == NULL) + continue; + if((! (ELF->sectionss[i].sh_flags & SHF_ALLOC)) || (ELF->sectionss[i].sh_size == 0)) + continue; + + // This is a loadable memory ... + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + // Where memory exist and waited share/private correspond + t_uint32 remoteData = elfhandle->segments[mapping->id].hostAddr + + ELF->sectionss[i].offsetInSegment * mapping->memEntSize; + + if(ELF->sectionss[i].sh_type != SHT_NOBITS) + { + LOG_INTERNAL(2, "loadSection(%s, 0x%x, 0x%x, 0x%08x)\n", + ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, + (t_uint32)ELF->sectionss[i].data, 0, 0); + + MMDSP_copySection((t_uint32)ELF->sectionss[i].data, remoteData, ELF->sectionss[i].trueDataSize); + } + else + { + LOG_INTERNAL(2, "bzeroSection(%s, 0x%x, 0x%x)\n", + ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, 0, 0, 0); + + MMDSP_bzeroSection(remoteData, ELF->sectionss[i].trueDataSize); + } + } + } + + return CM_OK; +} + + + +static const t_elfmemory* getSectionAddress( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_uint32 sectionIdx, + t_uint32 *sectionOffset, + t_cm_logical_address *sectionAddr) { + struct XXElf* ELF = elfhandle->ELF; + const t_elfmemory* mapping = ELF->sectionss[sectionIdx].meminfo; + + if(mapping != NULL) { + *sectionOffset = (elfhandle->segments[mapping->id].mpcAddr + + ELF->sectionss[sectionIdx].offsetInSegment); + + *sectionAddr = (t_cm_logical_address)(elfhandle->segments[mapping->id].hostAddr + + ELF->sectionss[sectionIdx].offsetInSegment * mapping->memEntSize); + } + + return mapping; +} + +static t_uint32 getSymbolAddress( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_uint32 symbolSectionIdx, + t_uint32 symbolOffet) { + struct XXElf* ELF = elfhandle->ELF; + const t_elfmemory* mapping = ELF->sectionss[symbolSectionIdx].meminfo; + + if(mapping == NULL) + return 0xFFFFFFFF; + // CM_ASSERT(elfhandle->segments[mapping->id].sumSize != 0); + // CM_ASSERT(elfhandle->sections[symbolSectionIdx].offsetInSegment != 0xFFFFFFFF); + + return elfhandle->segments[mapping->id].mpcAddr + + ELF->sectionss[symbolSectionIdx].offsetInSegment + + symbolOffet; +} + +#if 0 +t_bool ELFXX_getSymbolLocation( + const t_mpcal_memory *mpcalmemory, + t_elfdescription *elf, + char *symbolName, + const t_elfmemory **memory, + t_uint32 *offset) { + const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elf->elfdata; + const ElfXX_Shdr *sections = (ElfXX_Shdr*)&elf->elfdata[swapXword(header->e_shoff)]; + const char *strings = &elf->elfdata[swapXword(sections[swapHalf(header->e_shstrndx)].sh_offset)]; + int len = cm_StringLength(symbolName, 256); // TO BE FIXED + int i; + + for(i = 0; i < ELF->e_shnum; i++) + { + ElfXX_Sym* symtab; + const char* strtab; + unsigned int size, j; + + if(ELF->sectionss[i].sh_type != SHT_SYMTAB && ELF->sectionss[i].sh_type != SHT_DYNSYM) continue; + + // Section is a symbol table + symtab = (ElfXX_Sym*)&elf->elfdata[swapXword(sections[i].sh_offset)]; + strtab = &elf->elfdata[swapXword(sections[swapWord(sections[i].sh_link)].sh_offset)]; + size = ELF->sectionss[i].sh_size / (unsigned int)swapXword(sections[i].sh_entsize); + + for(j = 0; j < size; j++) { + const char* foundName = &strtab[swapWord(symtab[j].st_name)]; + + if(cm_StringCompare(symbolName, foundName, len) == 0) { + if(swapHalf(symtab[j].st_shndx) != SHN_UNDEF) { + int sectionIdx = (int)swapHalf(symtab[j].st_shndx); + ElfXX_Xword sh_flags = swapXword(sections[sectionIdx].sh_flags); + + *memory = mpcalmemory->getMappingByName(&strings[swapWord(sections[sectionIdx].sh_name)], + sh_flags & SHF_WRITE ? MEM_RW : (sh_flags & SHF_EXECINSTR ? MEM_X : MEM_RO)); + *offset = (t_uint32)swapXword(symtab[j].st_value); + + return 1; + } + } + } + } + return 0; +} +#endif + +t_cm_error ELF64_relocateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_memory_property property, + void *cbContext) { + struct XXElf* ELF = elfhandle->ELF; + int sec, n; + + // Loop on all relocation section + for(sec=0; sec < ELF->e_shnum; sec++) + { + t_cm_logical_address sectionAddr = 0; + t_uint32 sectionOffset = 0; + const t_elfmemory* mapping; + + if(ELF->sectionss[sec].relocations == NULL) + continue; + + // Relocate only section in memory + mapping = getSectionAddress(memories, + elfhandle, + sec, + §ionOffset, + §ionAddr); + if(mapping == NULL) + continue; + + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + LOG_INTERNAL(2, "relocSection(%s)\n", ELF->sectionss[sec].sectionName, 0, 0, 0, 0, 0); + + for(n = 0; n < ELF->sectionss[sec].relocationNumber; n++) + { + struct XXrelocation* relocation = &ELF->sectionss[sec].relocations[n]; + t_uint32 symbol_addr; + char* relocAddr = (char*)(sectionAddr + relocation->OffsetInElf * mapping->memEntSize); + + switch(relocation->st_shndx) { + case SHN_ABS: // Absolute external reference + symbol_addr = relocation->st_value; + break; + case SHN_UNDEF: // External reference + // LOG_INTERNAL(0, "cm_resolvSymbol(%d, %s)\n", relocation->type, relocation->symbol_name, 0,0, 0, 0); + symbol_addr = cm_resolvSymbol(cbContext, + relocation->type, + relocation->symbol_name, + relocAddr); + if(symbol_addr == 0x0) { // Not defined symbol + ERROR("Symbol %s not found\n", relocation->symbol_name, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } else if(symbol_addr == 0xFFFFFFFE) { // OOM + return CM_NO_MORE_MEMORY; + } else if(symbol_addr == 0xFFFFFFFF) { // Defined inside static binding + continue; + } + break; + default: // Internal reference in loaded section + symbol_addr = getSymbolAddress( + memories, + elfhandle, + (t_uint32)relocation->st_shndx, + relocation->st_value); + if(symbol_addr == 0xFFFFFFFF) { + ERROR("Symbol in section %s+%d not loaded\n", + ELF->sectionss[relocation->st_shndx].sectionName, + relocation->st_value, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + break; + } + + symbol_addr += relocation->r_addend; + + MMDSP_performRelocation( + relocation->type, + relocation->symbol_name, + symbol_addr, + relocAddr, + ELF->sectionss[sec].data + relocation->OffsetInElf * mapping->memEntSize, + sectionOffset + relocation->OffsetInElf); + } + } + } + + return CM_OK; +} + +t_cm_error ELF64_getRelocationMemory( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_uint32 offsetInNmf, + t_memory_reference *memory) { + struct XXElf* ELF = elfhandle->ELF; + const ElfXX_Rela* rel_start; + const ElfXX_Sym* relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->relaNmfSegmentSymbols; + + for(rel_start = (ElfXX_Rela*)elftmp->relaNmfSegment; rel_start < (ElfXX_Rela*)elftmp->relaNmfSegmentEnd; rel_start++) + { + if((t_uint32)swapXword(rel_start->r_offset) == offsetInNmf) + { + int strtab_index = ELFXX_R_SYM(swapXword(rel_start->r_info)); + int sectionIdx = (int)swapHalf(relaNmfSegmentSymbols[strtab_index].st_shndx); + + memory->memory = ELF->sectionss[sectionIdx].meminfo; + + if(memory->memory != NULL) { + memory->offset = ( + ELF->sectionss[sectionIdx].offsetInSegment + // Offset in Segment + (t_uint32)swapXword(relaNmfSegmentSymbols[strtab_index].st_value) + // Offset in Elf Section + (t_uint32)swapXword(rel_start->r_addend)); // Addend + + return CM_OK; + } else { + const char* symbol_name = &elftmp->relaNmfSegmentStrings[swapWord(relaNmfSegmentSymbols[strtab_index].st_name)]; + ERROR("Symbol %s not found\n", symbol_name, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + } + } + + ERROR("Unknown relocation error\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c new file mode 100644 index 00000000000..c6c316046b3 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -0,0 +1,435 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include <cm/engine/elf/inc/mmdsp-loadmap.h> +#include <cm/engine/elf/inc/mmdsp.h> +#include <cm/engine/dsp/inc/semaphores_dsp.h> +#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h> +#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h> + +#include <cm/engine/power_mgt/inc/power.h> + +#include <cm/engine/utils/inc/string.h> +#include <cm/engine/trace/inc/trace.h> +#include <cm/engine/memory/inc/domain.h> +#include <cm/engine/component/inc/instance.h> +#include <cm/engine/component/inc/component_type.h> +#include <inc/nmf-limits.h> + +#define LOADMAP_SEMAPHORE_USE_NB 7 + +static t_memory_handle headerHandle[NB_CORE_IDS] = {INVALID_MEMORY_HANDLE, }; +static struct LoadMapHdr *headerAddresses[NB_CORE_IDS] = {0, }; +static t_uint32 headerOffsets[NB_CORE_IDS] = {0, }; +static t_uint32 entryNumber[NB_CORE_IDS] = {0, }; + +#undef myoffsetof +#define myoffsetof(TYPE, MEMBER) ((unsigned int) &((TYPE *)0)->MEMBER) + +t_cm_error cm_DSPABI_AddLoadMap( + t_cm_domain_id domainId, + const char* templateName, + const char* localname, + t_memory_handle *memories, + void *componentHandle) +{ + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + int count=0; + struct LoadMapItem* curItem = NULL; + + if (headerHandle[coreId] == 0) /* Create loadmap header */ + { + headerHandle[coreId] = cm_DM_Alloc(domainId, SDRAM_EXT16, + sizeof(struct LoadMapHdr)/2, CM_MM_ALIGN_2WORDS, TRUE); + if (headerHandle[coreId] == INVALID_MEMORY_HANDLE) { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap in cm_DSPABI_AddLoadMap()\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + headerAddresses[coreId] = (struct LoadMapHdr*)cm_DSP_GetHostLogicalAddress(headerHandle[coreId]); + + headerAddresses[coreId]->nMagicNumber = LOADMAP_MAGIC_NUMBER; + headerAddresses[coreId]->nVersion = (LOADMAP_VERSION_MSB<<8)|(LOADMAP_VERSION_LSB); + headerAddresses[coreId]->nRevision = 0; + headerAddresses[coreId]->pFirstItem = 0; + + //Register Header into XRAM:2 + cm_DSP_GetDspAddress(headerHandle[coreId], &headerOffsets[coreId]); + cm_DSP_WriteXRamWord(coreId, 2, headerOffsets[coreId]); + } + + // update Header nRevision field + headerAddresses[coreId]->nRevision++; + + /* + * Build loadmap entry + */ + { + t_memory_handle handle; + struct LoadMapItem* pItem; + t_uint32 dspentry; + unsigned char* pos; + t_uint32 fnlen, lnlen; + t_uint32 fnlenaligned, lnlenaligned; + t_uint32 address; + t_uint32 postStringLength; + int i; + + postStringLength = cm_StringLength(".elf", 16); + fnlenaligned = fnlen = cm_StringLength(templateName, MAX_COMPONENT_FILE_PATH_LENGTH) + postStringLength + 2; + if((fnlenaligned % 2) != 0) fnlenaligned++; + lnlenaligned = lnlen = cm_StringLength(localname, MAX_TEMPLATE_NAME_LENGTH); + if((lnlenaligned % 2) != 0) lnlenaligned++; + + // Allocate new loap map + handle = cm_DM_Alloc(domainId, SDRAM_EXT16, + sizeof(struct LoadMapItem)/2 + (1 + fnlenaligned/2) + (1 + lnlenaligned/2), + CM_MM_ALIGN_2WORDS, TRUE); + if (handle == INVALID_MEMORY_HANDLE) { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap entry in cm_DSPABI_AddLoadMap\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + pItem = (struct LoadMapItem*)cm_DSP_GetHostLogicalAddress(handle); + cm_DSP_GetDspAddress(handle, &dspentry); + count++; + entryNumber[coreId]++; + + // Link this new loadmap with the previous one + if(headerAddresses[coreId]->pFirstItem == NULL) + headerAddresses[coreId]->pFirstItem = (struct LoadMapItem *)dspentry; + else + { + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem* curItem, *prevItem = NULL; + t_uint32 curItemDspAdress; + + if( + ((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) || + ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr)) + { + ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0); + + return CM_INVALID_DATA; + } + curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; + while(curItem->pNextItem != NULL) + { + if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr)) + { + if (prevItem == NULL) + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + 0, 0, 0, 0); + else + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + 0, 0, 0, 0); + return CM_INVALID_DATA; + } + curItemDspAdress = (t_uint32)curItem->pNextItem; + prevItem = curItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; + } + curItem->pNextItem = (struct LoadMapItem *)dspentry; + } + + // DSP Address of the string at the end of the load map + pos = (unsigned char*)pItem + sizeof(struct LoadMapItem); + + /* + * Set SolibFilename address information + * -> string = "./origfilename" + */ + pItem->pSolibFilename = (char*)(dspentry + sizeof(struct LoadMapItem) / 2); + *(t_uint16*)pos = fnlen; + pos += 2; + *pos++ = '.'; + *pos++ = '\\'; + for(i = 0; i < fnlen - 2 - postStringLength; i++) + { + *pos++ = (templateName[i] == '.') ? '\\' : templateName[i]; + } + *pos++ = '.'; + *pos++ = 'e'; + *pos++ = 'l'; + *pos++ = 'f'; + // add padding if needed + if ((t_uint32)pos & 1) + *pos++ = '\0'; + + /* + * Set Component Name address information + */ + if (lnlen != 0) + { + pItem->pComponentName = (char*)(dspentry + sizeof(struct LoadMapItem) / 2 + 1 + fnlenaligned / 2); + + *(t_uint16*)pos = lnlen; + pos += 2; + for(i = 0; i < lnlenaligned; i++) + { + // If not aligned null ending copied + *pos++ = localname[i]; + } + } + else + { + pItem->pComponentName = 0; + } + + /* + * Set PROG information + */ + if(memories[CODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[CODE_MEMORY_INDEX], &address); + pItem->pAddrProg = (void*)address; + + /* + * Set ERAMCODE information + */ + if(memories[ECODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[ECODE_MEMORY_INDEX], &address); + pItem->pAddrEmbProg = (void*)address; + + /* + * Set THIS information + */ + if(memories[PRIVATE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) { + // Standard component + cm_DSP_GetDspAddress(memories[PRIVATE_DATA_MEMORY_INDEX], &address); + } else if(memories[SHARE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) { + // Singleton component where data are shared (simulate THIS with shared memory) + cm_DSP_GetDspAddress(memories[SHARE_DATA_MEMORY_INDEX], &address); + } else { + // Component without data (take unique identifier -> arbitrary take host component handle) + address = (t_uint32)componentHandle; + } + pItem->pThis = (void*)address; + + /* + * Set ARM THIS information + */ + pItem->pARMThis = componentHandle; + + /* + * Set Link to null (end of list) + */ + pItem->pNextItem = 0; + + /* + * Set XROM information + */ + if(memories[XROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[XROM_MEMORY_INDEX], &address); + pItem->pXROM = (void*)address; + + /* + * Set YROM information + */ + if(memories[YROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[YROM_MEMORY_INDEX], &address); + pItem->pYROM = (void*)address; + + /* + * Set memory handle (not used externally) + */ + ((t_component_instance *)componentHandle)->loadMapHandle = handle; + } + + OSAL_mb(); + + if (count != entryNumber[coreId]) { + ERROR("AddLoadMap: corrumption, number of component differs: count=%d, expected %d (last item @ %p)\n", + count, entryNumber[coreId], curItem, 0, 0, 0); + return CM_INVALID_DATA; + } + return CM_OK; +} + +t_cm_error cm_DSPABI_RemoveLoadMap( + t_cm_domain_id domainId, + const char* templateName, + t_memory_handle *memories, + const char* localname, + void *componentHandle) +{ + struct LoadMapItem **prevItemReference; + t_uint32 prevItemReferenceDspAddress, curItemDspAdress; + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem* curItem = NULL; + + CM_ASSERT (headerHandle[coreId] != INVALID_MEMORY_HANDLE); + + /* parse list until we find this */ + prevItemReferenceDspAddress = 0x2; // DSP address of load map head pointer + prevItemReference = &headerAddresses[coreId]->pFirstItem; + curItemDspAdress = (t_uint32)*prevItemReference; + while(curItemDspAdress != 0x0) + { + if((curItemDspAdress < SDRAMMEM16_BASE_ADDR) || (curItemDspAdress > endSegmentAddr)) + { + ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + prevItemReferenceDspAddress, prevItemReference, 0, 0, 0, 0); + + /* free the entry anyway to avoid leakage */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); + + return CM_OK; + } + + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + + if(curItem->pARMThis == componentHandle) + { + // Remove component from loadmap + + /* take local semaphore */ + cm_DSP_SEM_Take(coreId,LOADMAP_SEMAPHORE_USE_NB); + + /* remove element from list */ + *prevItemReference = curItem->pNextItem; + + /* update nRevision field in header */ + headerAddresses[coreId]->nRevision++; + + /* If this is the last item, deallocate !!! */ + if(headerAddresses[coreId]->pFirstItem == NULL) + { + // Deallocate memory + cm_DM_Free(headerHandle[coreId], TRUE); + headerHandle[coreId] = INVALID_MEMORY_HANDLE; + + //Register Header into XRAM:2 + cm_DSP_WriteXRamWord(coreId, 2, 0); + } + + /* deallocate memory */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); + + /* be sure memory is updated before releasing local semaphore */ + OSAL_mb(); + + /* release local semaphore */ + cm_DSP_SEM_Give(coreId,LOADMAP_SEMAPHORE_USE_NB); + + entryNumber[coreId]--; + + return CM_OK; + } + + prevItemReferenceDspAddress = curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem); + prevItemReference = &curItem->pNextItem; + curItemDspAdress = (t_uint32)*prevItemReference; + }; + + ERROR("Memory corruption in MMDSP: component not in LoadMap %s\n", localname, 0, 0, 0, 0, 0); + + /* free the entry anyway to avoid leakage */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); + + return CM_OK; +} + +#if 0 +t_cm_error cm_DSPABI_CheckLoadMap_nolock(t_nmf_core_id coreId) +{ + int count=0; + static int dump = 5; + struct LoadMapItem* curItem = NULL; + + if (!dump) + return CM_OK; + if (headerHandle[coreId] == 0) /* No load map yet */ + return CM_OK; + + { + // No entry in loadmap + if(headerAddresses[coreId]->pFirstItem == NULL) + return CM_OK; + + { + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem *prevItem=NULL; + t_uint32 curItemDspAdress; + + if (((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) || + ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr)) + { + ERROR("CheckLoadMap: Memory corruption in MMDSP at first item: at data DSP address=%x or ARM address=%x\n", + headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } + curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); + count++; + while(curItem->pNextItem != NULL) + { + if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr)) + { + if (!prevItem) + ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n" + "Previous (first) component name %s<%s>\n", + count, + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + (char*)(((t_component_instance *)&curItem->pARMThis)->pathname), + (char*)(((t_component_instance *)&curItem->pARMThis)->Template->name), 0); + else + ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n" + "Previous valid component name %s<%s>", + count, + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname), + (char*)(((t_component_instance *)&prevItem->pARMThis)->Template->name), 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } + curItemDspAdress = (t_uint32)curItem->pNextItem; + prevItem = curItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; + } + } + + } + + if (count != entryNumber[coreId]) { + ERROR("CheckLoadMap: number of component differs: count=%d, expected %d (last item @ %p)\n", count, entryNumber[coreId], + curItem, 0, 0, 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } + return CM_OK; +} + +t_cm_error cm_DSPABI_CheckLoadMap(t_nmf_core_id coreId) +{ + t_cm_error error; + OSAL_LOCK_API(); + error = cm_DSPABI_CheckLoadMap_nolock(coreId); + OSAL_UNLOCK_API(); + return error; +} +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c new file mode 100644 index 00000000000..93d910a5ed6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c @@ -0,0 +1,6 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include <cm/engine/elf/inc/mpcal.h> |