diff options
36 files changed, 2567 insertions, 869 deletions
diff --git a/core/arch/arm/kernel/elf32.h b/core/arch/arm/kernel/elf32.h new file mode 100644 index 00000000..d3742085 --- /dev/null +++ b/core/arch/arm/kernel/elf32.h @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/core/arch/arm/kernel/elf64.h b/core/arch/arm/kernel/elf64.h new file mode 100644 index 00000000..c468dcda --- /dev/null +++ b/core/arch/arm/kernel/elf64.h @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/core/arch/arm/kernel/elf_common.h b/core/arch/arm/kernel/elf_common.h new file mode 100644 index 00000000..dd8cd507 --- /dev/null +++ b/core/arch/arm/kernel/elf_common.h @@ -0,0 +1,1006 @@ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#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 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#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. */ +#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. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + 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 mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon 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 proc. */ +#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 Cores Tangent-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 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 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson 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_AARCH64 183 /* AArch64 (64-bit ARM) */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* e_flags for EM_ARM */ +#define EF_ARM_ABI_VERSION 0x05000000 /* ABI version 5 */ +#define EF_ARM_ABIMASK 0xFF000000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 /* ABI version 5 and later */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + pre-emption map. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + attributes. */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ +#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ +#define NT_PROCSTAT_FILES 9 /* Procstat files data. */ +#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ +#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ +#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ +#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ +#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ +#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ +#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ + +#define R_AARCH64_RELATIVE 1027 + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_64 18 /* Direct 64 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_IRELATIVE 37 + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/core/arch/arm/kernel/elf_load.c b/core/arch/arm/kernel/elf_load.c new file mode 100644 index 00000000..d5c26b8b --- /dev/null +++ b/core/arch/arm/kernel/elf_load.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <types_ext.h> +#include <tee_api_types.h> +#include <tee_api_defines.h> +#include <kernel/tee_misc.h> +#include <tee/tee_cryp_provider.h> +#include <stdlib.h> +#include <string.h> +#include <util.h> +#include <trace.h> +#include "elf_load.h" +#include "elf_common.h" +#include "elf32.h" + + +struct elf_load_state { + uint8_t *nwdata; + size_t nwdata_len; + + void *hash_ctx; + uint32_t hash_algo; + + size_t next_offs; + + void *ta_head; + size_t ta_head_size; + + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + + size_t vasize; + Elf32_Shdr *shdr; +}; + +static TEE_Result advance_to(struct elf_load_state *state, size_t offs) +{ + TEE_Result res; + + if (offs < state->next_offs) + return TEE_ERROR_BAD_STATE; + if (offs == state->next_offs) + return TEE_SUCCESS; + + if (offs > state->nwdata_len) + return TEE_ERROR_SECURITY; + + res = crypto_ops.hash.update(state->hash_ctx, state->hash_algo, + state->nwdata + state->next_offs, + offs - state->next_offs); + if (res != TEE_SUCCESS) + return res; + state->next_offs = offs; + return res; +} + +static TEE_Result copy_to(struct elf_load_state *state, + void *dst, size_t dst_size, size_t dst_offs, + size_t offs, size_t len) +{ + TEE_Result res; + + res = advance_to(state, offs); + if (res != TEE_SUCCESS) + return res; + if (!len) + return TEE_SUCCESS; + + if (len > dst_size || (len + dst_offs) > dst_size) + return TEE_ERROR_SECURITY; + + if (!core_is_buffer_inside(state->nwdata + offs, len, + state->nwdata, state->nwdata_len)) + return TEE_ERROR_SECURITY; + + memcpy((uint8_t *)dst + dst_offs, state->nwdata + offs, len); + res = crypto_ops.hash.update(state->hash_ctx, state->hash_algo, + (uint8_t *)dst + dst_offs, len); + if (res != TEE_SUCCESS) + return res; + state->next_offs = offs + len; + return res; +} + +static TEE_Result alloc_and_copy_to(void **p, struct elf_load_state *state, + size_t offs, size_t len) +{ + TEE_Result res; + void *buf; + + buf = malloc(len); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_to(state, buf, len, 0, offs, len); + if (res == TEE_SUCCESS) + *p = buf; + else + free(buf); + return res; +} + +TEE_Result elf_load_init(void *hash_ctx, uint32_t hash_algo, uint8_t *nwdata, + size_t nwdata_len, struct elf_load_state **ret_state) +{ + struct elf_load_state *state; + + state = calloc(1, sizeof(*state)); + if (!state) + return TEE_ERROR_OUT_OF_MEMORY; + state->hash_ctx = hash_ctx; + state->hash_algo = hash_algo; + state->nwdata = nwdata; + state->nwdata_len = nwdata_len; + *ret_state = state; + return TEE_SUCCESS; +} + +TEE_Result elf_load_head(struct elf_load_state *state, size_t head_size, + void **head, size_t *vasize) +{ + TEE_Result res; + size_t n; + void *p; + Elf32_Ehdr *ehdr; + + /* + * The ELF resides in shared memory, to avoid attacks based on + * modifying the ELF while we're parsing it here we only read each + * byte from the ELF once. We're also hashing the ELF while reading + * so we're limited to only read the ELF sequentially from start to + * end. + */ + + res = alloc_and_copy_to(&p, state, 0, sizeof(Elf32_Ehdr)); + if (res != TEE_SUCCESS) + return res; + ehdr = p; + state->ehdr = ehdr; + + if (!IS_ELF(*ehdr) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION || + (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) || + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) + return TEE_ERROR_BAD_FORMAT; + + /* + * Program headers are supposed to be arranged as: + * PT_LOAD [0] : .ta_head ... + * ... + * PT_LOAD [n] + * + * .ta_head must be located first in the first program header, + * which also has to be of PT_LOAD type. + * + * A PT_DYNAMIC segment may appear, but is ignored. Any other + * segment except PT_LOAD and PT_DYNAMIC will cause an error. All + * sections not included by a PT_LOAD segment are ignored. + */ + if (ehdr->e_phnum < 1) + return TEE_ERROR_BAD_FORMAT; + res = alloc_and_copy_to(&p, state, ehdr->e_phoff, + ehdr->e_phnum * sizeof(Elf32_Phdr)); + if (res != TEE_SUCCESS) + return res; + state->phdr = p; + + /* + * Check that the first program header is a PT_LOAD (not strictly + * needed but our link script is supposed to arrange it that way) + * and that it starts at virtual address 0. + */ + if (state->phdr[0].p_type != PT_LOAD || state->phdr[0].p_vaddr != 0) + return TEE_ERROR_BAD_FORMAT; + + /* + * Calculate amount of required virtual memory for TA. Find the max + * address used by a PT_LOAD type. Note that last PT_LOAD type + * dictates the total amount of needed memory. Eventual holes in + * the memory will also be allocated. + * + * Note that this loop will terminate at n = 0 if not earlier + * as we already know from above that state->phdr[0].p_type == PT_LOAD + */ + n = ehdr->e_phnum - 1; + while (state->phdr[n].p_type != PT_LOAD) + n--; + state->vasize = state->phdr[n].p_vaddr + state->phdr[n].p_memsz; + + /* + * Read .ta_head from first segment, make sure the segment is large + * enough. We're only interested in seeing that the + * TA_FLAG_EXEC_DDR flag is set. If that's true we set that flag in + * the TA context to enable mapping the TA. Later when this + * function has returned and the hash has been verified the flags + * field will be updated with eventual other flags. + */ + if (state->phdr[0].p_filesz < head_size) + return TEE_ERROR_BAD_FORMAT; + res = alloc_and_copy_to(&p, state, state->phdr[0].p_offset, head_size); + if (res != TEE_SUCCESS) + return res; + state->ta_head = p; + state->ta_head_size = head_size; + + *head = state->ta_head; + *vasize = state->vasize; + return TEE_SUCCESS; +} + +static TEE_Result elf_process_rel(struct elf_load_state *state, size_t rel_sidx, + vaddr_t vabase) +{ + Elf32_Shdr *shdr = state->shdr; + Elf32_Rel *rel; + Elf32_Rel *rel_end; + size_t sym_tab_idx; + Elf32_Sym *sym_tab = NULL; + size_t num_syms = 0; + + if (shdr[rel_sidx].sh_entsize != sizeof(Elf32_Rel)) + return TEE_ERROR_BAD_FORMAT; + + sym_tab_idx = shdr[rel_sidx].sh_link; + if (sym_tab_idx) { + if (sym_tab_idx >= state->ehdr->e_shnum) + return TEE_ERROR_BAD_FORMAT; + + if (shdr[sym_tab_idx].sh_entsize != sizeof(Elf32_Sym)) + return TEE_ERROR_BAD_FORMAT; + + /* Check the address is inside TA memory */ + if (shdr[sym_tab_idx].sh_addr > state->vasize || + (shdr[sym_tab_idx].sh_addr + + shdr[sym_tab_idx].sh_size) > state->vasize) + return TEE_ERROR_BAD_FORMAT; + + sym_tab = (Elf32_Sym *)(vabase + shdr[sym_tab_idx].sh_addr); + if (!TEE_ALIGNMENT_IS_OK(sym_tab, Elf32_Sym)) + return TEE_ERROR_BAD_FORMAT; + + num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); + } + + /* Check the address is inside TA memory */ + if (shdr[rel_sidx].sh_addr >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + rel = (Elf32_Rel *)(vabase + shdr[rel_sidx].sh_addr); + if (!TEE_ALIGNMENT_IS_OK(rel, Elf32_Rel)) + return TEE_ERROR_BAD_FORMAT; + + /* Check the address is inside TA memory */ + if ((shdr[rel_sidx].sh_addr + shdr[rel_sidx].sh_size) >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); + for (; rel < rel_end; rel++) { + Elf32_Addr *where; + size_t sym_idx; + + /* Check the address is inside TA memory */ + if (rel->r_offset >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + + where = (Elf32_Addr *)(vabase + rel->r_offset); + if (!TEE_ALIGNMENT_IS_OK(where, Elf32_Addr)) + return TEE_ERROR_BAD_FORMAT; + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_ABS32: + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + return TEE_ERROR_BAD_FORMAT; + + *where += vabase + sym_tab[sym_idx].st_value; + break; + case R_ARM_RELATIVE: + *where += vabase; + break; + default: + EMSG("Unknown relocation type %d", + ELF32_R_TYPE(rel->r_info)); + return TEE_ERROR_BAD_FORMAT; + } + } + return TEE_SUCCESS; +} + +TEE_Result elf_load_body(struct elf_load_state *state, vaddr_t vabase) +{ + TEE_Result res; + size_t n; + void *p; + uint8_t *dst = (uint8_t *)vabase; + Elf32_Ehdr *ehdr = state->ehdr; + Elf32_Phdr *phdr = state->phdr; + + /* + * Zero initialize everything to make sure that all memory not + * updated from the ELF is zero (covering .bss and eventual gaps). + */ + memset(dst, 0, state->vasize); + + /* + * Copy the segments + */ + memcpy(dst, state->ta_head, state->ta_head_size); + res = copy_to(state, dst, state->vasize, + phdr[0].p_vaddr + state->ta_head_size, + phdr[0].p_offset + state->ta_head_size, + phdr[0].p_filesz - state->ta_head_size); + if (res != TEE_SUCCESS) + return res; + + for (n = 1; n < ehdr->e_phnum; n++) { + if (phdr[n].p_type != PT_LOAD) + continue; + + res = copy_to(state, dst, state->vasize, phdr[n].p_vaddr, + phdr[n].p_offset, phdr[n].p_filesz); + if (res != TEE_SUCCESS) + return res; + } + + /* + * We have now loaded all segments into TA memory, now we need to + * process relocation information. To find relocation information + * we need to locate the section headers. The section headers are + * located somewhere between the last segment and the end of the + * ELF. + */ + if (ehdr->e_shoff) { + /* We have section headers */ + res = alloc_and_copy_to(&p, state, ehdr->e_shoff, + ehdr->e_shnum * sizeof(Elf32_Shdr)); + if (res != TEE_SUCCESS) + return res; + state->shdr = p; + } + + /* Hash until end of ELF */ + res = advance_to(state, state->nwdata_len); + if (res != TEE_SUCCESS) + return res; + + if (state->shdr) { + /* Process relocation */ + for (n = 0; n < ehdr->e_shnum; n++) { + if (state->shdr[n].sh_type == SHT_RELA) + return TEE_ERROR_NOT_IMPLEMENTED; + else if (state->shdr[n].sh_type == SHT_REL) { + res = elf_process_rel(state, n, vabase); + if (res != TEE_SUCCESS) + return res; + } + } + } + + return TEE_SUCCESS; +} + +void elf_load_final(struct elf_load_state *state) +{ + if (state) { + free(state->ta_head); + free(state->ehdr); + free(state->phdr); + free(state->shdr); + free(state); + } +} diff --git a/core/arch/arm/include/kernel/kta_types.h b/core/arch/arm/kernel/elf_load.h index baa3a1a8..dbe8d164 100644 --- a/core/arch/arm/include/kernel/kta_types.h +++ b/core/arch/arm/kernel/elf_load.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,26 +24,19 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef ELF_LOAD_H +#define ELF_LOAD_H -#ifndef KTA_TYPES_H -#define KTA_TYPES_H +#include <types_ext.h> +#include <tee_api_types.h> -#include <stdint.h> +struct elf_load_state; -typedef struct kta_signed_header { - uint32_t magic; - uint16_t size_of_signed_header; - uint16_t size_of_signature; - uint32_t sign_hash_type; /* see t_hash_type */ - uint32_t signature_type; /* see t_signature_type */ - uint32_t hash_type; /* see t_hash_type */ - uint32_t payload_type; /* see enum kta_payload_type */ - uint32_t flags; /* reserved */ - uint32_t size_of_payload; - uint32_t sw_vers_nbr; - uint32_t load_address; - uint32_t startup_address; - uint32_t spare; /* reserved */ -} kta_signed_header_t; +TEE_Result elf_load_init(void *hash_ctx, uint32_t hash_algo, uint8_t *nwdata, + size_t nwdata_len, struct elf_load_state **state); +TEE_Result elf_load_head(struct elf_load_state *state, size_t head_size, + void **head, size_t *vasize); +TEE_Result elf_load_body(struct elf_load_state *state, vaddr_t vabase); +void elf_load_final(struct elf_load_state *state); -#endif /* End of kta_types.h */ +#endif /*ELF_LOAD_H*/ diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk index ac31e4a0..d0225941 100644 --- a/core/arch/arm/kernel/sub.mk +++ b/core/arch/arm/kernel/sub.mk @@ -1,4 +1,5 @@ srcs-y += tee_ta_manager.c +srcs-y += elf_load.c srcs-y += tee_time.c srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c diff --git a/core/arch/arm/kernel/tee_ta_manager.c b/core/arch/arm/kernel/tee_ta_manager.c index b02b22d9..9098ffe7 100644 --- a/core/arch/arm/kernel/tee_ta_manager.c +++ b/core/arch/arm/kernel/tee_ta_manager.c @@ -41,6 +41,8 @@ #include <mm/tee_mmu.h> #include <kernel/tee_misc.h> #include <tee/tee_svc_cryp.h> +#include <tee/tee_cryp_provider.h> +#include <tee/tee_cryp_utl.h> #include <kernel/tee_common.h> #include <kernel/tee_ta_manager.h> #include <kernel/tee_ta_manager_unpg.h> @@ -54,14 +56,18 @@ #include <tee/tee_svc_storage.h> #include <kernel/tee_time.h> #include <sm/tee_mon.h> -#include "user_ta_header.h" +#include <user_ta_header.h> #include <mm/core_memprot.h> #include <mm/core_mmu.h> #include <kernel/thread.h> #include <sm/teesmc.h> #include <kernel/tee_misc.h> +#include <ta_pub_key.h> #include <kernel/tee_kta_trace.h> #include <kernel/trace_ta.h> +#include <signed_hdr.h> +#include <utee_defines.h> +#include "elf_load.h" /* * Use this invalid ID for a static TA, since @@ -236,373 +242,225 @@ static struct tee_ta_ctx *tee_ta_context_find(const TEE_UUID *uuid) struct tee_ta_ctx *ctx; TAILQ_FOREACH(ctx, &tee_ctxes, link) { - if (memcmp(&ctx->head->uuid, uuid, sizeof(TEE_UUID)) == 0) + if (memcmp(&ctx->uuid, uuid, sizeof(TEE_UUID)) == 0) return ctx; } return NULL; } -static void tee_ta_init_got(struct tee_ta_ctx *const ctx) -{ - uint32_t *ptr; - uint32_t *end_ptr; - uint32_t va_start; - - /* - * GOT and find_service_addr follows right after ro section. - */ - if ((TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size) == 0) - return; - - va_start = ctx->load_addr; - - ptr = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size); - end_ptr = ptr + (TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size) / - sizeof(uint32_t); - - while (ptr < end_ptr) { - *ptr += va_start; -#ifdef PAGER_DEBUG_PRINT - DMSG("GOT [%p] = 0x%x", (void *)ptr, *ptr); -#endif - ptr++; - } -} - -static void tee_ta_init_zi(struct tee_ta_ctx *const ctx) +static TEE_Result tee_ta_load_header(const struct shdr *signed_ta, + struct shdr **sec_shdr) { - /* setup ZI data */ - vaddr_t start = tee_ta_get_exec(ctx) + - ctx->head->rw_size + ctx->head->ro_size; - - memset((void *)start, 0, ctx->head->zi_size); -} + size_t s; -/* - * Process rel.dyn - */ -static void tee_ta_init_reldyn(struct tee_ta_ctx *const ctx) -{ - uint32_t rel_dyn_size = ctx->head->rel_dyn_got_size >> 16; - uint32_t n; - vaddr_t saddr = tee_ta_get_exec(ctx) + ctx->head->ro_size - - rel_dyn_size; - - for (n = 0; n < rel_dyn_size; n += sizeof(struct ta_rel_dyn)) { - struct ta_rel_dyn *rel_dyn = (struct ta_rel_dyn *)(saddr + n); - uint32_t *data; - - if (rel_dyn->info != 0x17) { - EMSG("Unknown rel_dyn info 0x%x", rel_dyn->info); - TEE_ASSERT(0); - } - - data = (uint32_t *)((vaddr_t)ctx->load_addr + rel_dyn->addr); - *data += ctx->load_addr; -#ifdef PAGER_DEBUG_PRINT - DMSG("rel.dyn [%p] = 0x%x", (void *)data, *data); -#endif - } -} - -/* - * Setup global variables initialized from TEE Core - */ -static void tee_ta_init_heap(struct tee_ta_ctx *const ctx, size_t heap_size) -{ - uint32_t *data; - tee_uaddr_t heap_start_addr; - vaddr_t va_start; - - /* - * User TA - * - * Heap base follows right after GOT - */ + if (!tee_vbuf_is_non_sec(signed_ta, sizeof(*signed_ta))) + return TEE_ERROR_SECURITY; - core_mmu_get_user_va_range(&va_start, NULL); - /* XXX this function shouldn't know this mapping */ - heap_start_addr = va_start + CORE_MMU_USER_CODE_SIZE - heap_size; + s = SHDR_GET_SIZE(signed_ta); + if (!tee_vbuf_is_non_sec(signed_ta, s)) + return TEE_ERROR_SECURITY; - data = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size + - (ctx->head->rel_dyn_got_size & TA_HEAD_GOT_MASK)); + /* Copy signed header into secure memory */ + *sec_shdr = malloc(s); + if (!*sec_shdr) + return TEE_ERROR_OUT_OF_MEMORY; + memcpy(*sec_shdr, signed_ta, s); - *data = heap_start_addr; -#ifdef PAGER_DEBUG_PRINT - DMSG("heap_base [%p] = 0x%x", (void *)data, *data); -#endif + return TEE_SUCCESS; } -static TEE_Result tee_ta_load_header(const kta_signed_header_t *signed_ta, - kta_signed_header_t **sec_signed_ta, ta_head_t **sec_head, - const uint8_t **nmem_ta) +static TEE_Result tee_ta_load_check_shdr(struct shdr *shdr) { + struct rsa_public_key key; TEE_Result res; - size_t sz_sign_header; - size_t sz_ta_head; - size_t sz_hash_type; - size_t sz_ro; - size_t sz_rw; - size_t sz_hashes; - size_t num_hashes; - size_t sz_funcs; - const ta_head_t *nmem_head; - ta_head_t *head = NULL; - uint8_t *nmem_hashes; - uint8_t *hashes; - - if (!tee_vbuf_is_non_sec(signed_ta, sizeof(*signed_ta))) - return TEE_ERROR_SECURITY; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); + size_t hash_size; - sz_sign_header = signed_ta->size_of_signed_header; - if (!tee_vbuf_is_non_sec(signed_ta, sz_sign_header)) + if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA) return TEE_ERROR_SECURITY; - nmem_head = (const void *)((uint8_t *)(signed_ta) + sz_sign_header); - if (!tee_vbuf_is_non_sec(nmem_head, sizeof(*nmem_head))) - return TEE_ERROR_SECURITY; - - sz_ro = nmem_head->ro_size; - sz_rw = nmem_head->rw_size; - - /* Obviously a fake TA since there's no code or data */ - if ((sz_ro + sz_rw) == 0) + if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) return TEE_ERROR_SECURITY; - /* One hash per supplied page of code and data */ - num_hashes = ((sz_ro + sz_rw - 1) >> SMALL_PAGE_SHIFT) + 1; - -#ifdef CFG_NO_TA_HASH_SIGN - sz_hash_type = 0; -#else - /* COPY HEADERS & HASHES: ta_head + ta_func_head(s) + hashes */ - if (tee_hash_get_digest_size(nmem_head->hash_type, &sz_hash_type) != - TEE_SUCCESS) { - DMSG("warning: invalid signed header: invalid hash id found!"); + res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), + &hash_size); + if (res != TEE_SUCCESS) + return res; + if (hash_size != shdr->hash_size) return TEE_ERROR_SECURITY; - } -#endif - - sz_hashes = sz_hash_type * num_hashes; - sz_funcs = nmem_head->nbr_func * sizeof(ta_func_head_t); - sz_ta_head = sizeof(*head) + sz_funcs + sz_hashes; - if (!tee_vbuf_is_non_sec(nmem_head, sz_ta_head - sz_hashes)) - return TEE_ERROR_SECURITY; + if (!crypto_ops.acipher.alloc_rsa_public_key || + !crypto_ops.acipher.rsassa_verify || + !crypto_ops.bignum.bin2bn || !crypto_ops.bignum.free) + return TEE_ERROR_NOT_SUPPORTED; - /* Copy TA header into secure memory */ - head = malloc(sz_ta_head); - if (!head) - return TEE_ERROR_OUT_OF_MEMORY; - memcpy(head, nmem_head, sz_ta_head - sz_hashes); + res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size); + if (res != TEE_SUCCESS) + return res; - /* - * Check that the GOT ends up at a properly aligned address. - * See tee_ta_init_got() for update of GOT. - */ - if ((head->ro_size % 4) != 0) { - DMSG("Bad ro_size %u", head->ro_size); - res = TEE_ERROR_BAD_FORMAT; + res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res != TEE_SUCCESS) goto out; - } - - /* Copy hashes into secure memory */ - hashes = (uint8_t *)head + sz_funcs; - nmem_hashes = (uint8_t *)nmem_head + sz_funcs + - head->ro_size + head->rw_size; - memcpy(hashes, nmem_hashes, sz_hashes); - - /* Copy signed header into secure memory */ - *sec_signed_ta = malloc(sz_sign_header); - if (!*sec_signed_ta) { - res = TEE_ERROR_OUT_OF_MEMORY; + res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus, + ta_pub_key_modulus_size, key.n); + if (res != TEE_SUCCESS) goto out; - } - memcpy(*sec_signed_ta, signed_ta, sz_sign_header); - - *sec_head = head; - *nmem_ta = (const uint8_t *)nmem_head; - res = TEE_SUCCESS; + res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1, + SHDR_GET_HASH(shdr), shdr->hash_size, + SHDR_GET_SIG(shdr), shdr->sig_size); out: - if (res != TEE_SUCCESS) { - free(head); - } + crypto_ops.bignum.free(key.n); + crypto_ops.bignum.free(key.e); return res; } -static TEE_Result tee_ta_load_check_head_integrity( - kta_signed_header_t *signed_ta __unused, - ta_head_t *head __unused) -{ - /* - * This is where the signature of the signed header is verified - * and that the payload that "head" is a valid payload for - * that signed header. - * - * If this function returns success "head" together with - * the appended hashes are OK and we can continue to load - * the TA. - */ - return TEE_SUCCESS; -} - -static TEE_Result tee_ta_load_user_ta(struct tee_ta_ctx *ctx, - ta_head_t *sec_head, const void *nmem_ta, - size_t *heap_size) +static TEE_Result tee_ta_load_elf(struct tee_ta_ctx *ctx, struct shdr *shdr, + const struct shdr *nmem_shdr) { TEE_Result res; - size_t size; - ta_func_head_t *ta_func_head; - struct user_ta_sub_head *sub_head; - /* man_flags: mandatory flags */ - uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; - /* opt_flags: optional flags */ - uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE | - TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS; struct tee_ta_param param = { 0 }; - void *dst; - - /* full required execution size (not stack etc...) */ - size = ctx->head->ro_size + ctx->head->rw_size + ctx->head->zi_size; - - if (ctx->num_res_funcs != 2) - return TEE_ERROR_BAD_FORMAT; - - ta_func_head = (ta_func_head_t *)((vaddr_t)ctx->head + - sizeof(ta_head_t)); - - sub_head = (struct user_ta_sub_head *)&ta_func_head[ - ctx->head->nbr_func - ctx->num_res_funcs]; + size_t hash_ctx_size; + void *hash_ctx = NULL; + uint32_t hash_algo; + uint8_t *nwdata = (uint8_t *)nmem_shdr + SHDR_GET_SIZE(shdr); + size_t nwdata_len = shdr->img_size; + void *digest = NULL; + struct elf_load_state *elf_state = NULL; + struct ta_head *ta_head; + void *p; + size_t vasize; + + if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init || + !crypto_ops.hash.update || !crypto_ops.hash.final) { + res = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); + res = crypto_ops.hash.get_ctx_size(hash_algo, &hash_ctx_size); + if (res != TEE_SUCCESS) + goto out; + hash_ctx = malloc(hash_ctx_size); + if (!hash_ctx) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + res = crypto_ops.hash.init(hash_ctx, hash_algo); + if (res != TEE_SUCCESS) + goto out; + res = crypto_ops.hash.update(hash_ctx, hash_algo, + (uint8_t *)shdr, sizeof(struct shdr)); + if (res != TEE_SUCCESS) + goto out; + res = elf_load_init(hash_ctx, hash_algo, nwdata, nwdata_len, + &elf_state); + if (res != TEE_SUCCESS) + goto out; - /* - * sub_head is the end area of func_head; the 2 last - * (2 'resisdent func') func_head area. - * sub_head structure is... twice the func_head struct. magic. - * sub_head stores the flags, heap_size, stack_size. - */ - COMPILE_TIME_ASSERT((sizeof(struct user_ta_sub_head)) == - (2 * sizeof(struct user_ta_func_head))); + res = elf_load_head(elf_state, sizeof(struct ta_head), &p, &vasize); + if (res != TEE_SUCCESS) + goto out; + ta_head = p; - /* check input flags bitmask consistency and save flags */ - if ((sub_head->flags & opt_flags) != sub_head->flags || - (sub_head->flags & man_flags) != man_flags) { - EMSG("TA flag issue: flags=%x opt=%X man=%X", - sub_head->flags, opt_flags, man_flags); - return TEE_ERROR_BAD_FORMAT; + ctx->mm = tee_mm_alloc(&tee_mm_sec_ddr, vasize); + if (!ctx->mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } - ctx->flags = sub_head->flags; - - /* Check if multi instance && single session config */ - if (((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) && - ((ctx->flags & TA_FLAG_MULTI_SESSION) == 0)) { - /* - * assume MultiInstance/SingleSession, - * same as MultiInstance/MultiSession - */ - ctx->flags |= TA_FLAG_MULTI_SESSION; + /* Currently all TA must execute from DDR */ + if (!(ta_head->flags & TA_FLAG_EXEC_DDR)) { + res = TEE_ERROR_BAD_FORMAT; + goto out; } + /* Temporary assignment to setup memory mapping */ + ctx->flags = TA_FLAG_EXEC_DDR; /* Ensure proper aligment of stack */ - ctx->stack_size = ROUNDUP(sub_head->stack_size, - TEE_TA_STACK_ALIGNMENT); - - *heap_size = sub_head->heap_size; + ctx->stack_size = ROUNDUP(ta_head->stack_size, + TEE_TA_STACK_ALIGNMENT); - /* - * Allocate heap and stack - */ - ctx->mm_heap_stack = tee_mm_alloc(&tee_mm_sec_ddr, - *heap_size + ctx->stack_size); - if (!ctx->mm_heap_stack) { - EMSG("Failed to allocate %zu bytes\n", - *heap_size + ctx->stack_size); - EMSG(" of memory for user heap and stack\n"); - return TEE_ERROR_OUT_OF_MEMORY; + ctx->mm_stack = tee_mm_alloc(&tee_mm_sec_ddr, ctx->stack_size); + if (!ctx->mm_stack) { + EMSG("Failed to allocate %zu bytes for user stack", + ctx->stack_size); + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } /* - * Note that only User TA can be supported in DDR - * if executing in DDR, the size of the execution area - */ - size += sizeof(ta_head_t) + - sec_head->nbr_func * sizeof(ta_func_head_t) + - (sec_head->rel_dyn_got_size & TA_HEAD_GOT_MASK); - - ctx->mm = tee_mm_alloc(&tee_mm_sec_ddr, size); - if (!ctx->mm) - return TEE_ERROR_OUT_OF_MEMORY; - - /* - * Copy TA into reserved memory space (DDR). + * Map physical memory into TA virtual memory */ res = tee_mmu_init(ctx); if (res != TEE_SUCCESS) - return res; + goto out; res = tee_mmu_map(ctx, ¶m); - if (res != TEE_SUCCESS) { - EMSG("call tee_mmu_map_uta() failed %X", res); - return res; - } + if (res != TEE_SUCCESS) + goto out; tee_mmu_set_ctx(ctx); - dst = (void *)tee_mmu_get_load_addr(ctx); - if (!tee_vbuf_is_non_sec(nmem_ta, size)) { - EMSG("User TA isn't in non-secure memory"); - return TEE_ERROR_SECURITY; + res = elf_load_body(elf_state, tee_mmu_get_load_addr(ctx)); + if (res != TEE_SUCCESS) + goto out; + + digest = malloc(shdr->hash_size); + if (!digest) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } - memcpy(dst, nmem_ta, size); - cache_maintenance_l1(DCACHE_AREA_CLEAN, dst, size); - cache_maintenance_l1(ICACHE_AREA_INVALIDATE, dst, size); + res = crypto_ops.hash.final(hash_ctx, hash_algo, digest, + shdr->hash_size); + if (res != TEE_SUCCESS) + goto out; - ctx->load_addr = tee_mmu_get_load_addr(ctx); + if (memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size) != 0) + res = TEE_ERROR_SECURITY; - return TEE_SUCCESS; + cache_maintenance_l1(DCACHE_AREA_CLEAN, + (void *)tee_mmu_get_load_addr(ctx), vasize); + cache_maintenance_l1(ICACHE_AREA_INVALIDATE, + (void *)tee_mmu_get_load_addr(ctx), vasize); +out: + elf_load_final(elf_state); + free(digest); + free(hash_ctx); + return res; } -static void tee_ta_load_init_user_ta(struct tee_ta_ctx *ctx, size_t heap_size) -{ - /* Init rel.dyn, GOT, ZI and heap */ - tee_ta_init_reldyn(ctx); - tee_ta_init_got(ctx); - tee_ta_init_heap(ctx, heap_size); - tee_ta_init_zi(ctx); -} + /*----------------------------------------------------------------------------- * Loads TA header and hashes. * Verifies the TA signature. * Returns session ptr and TEE_Result. *---------------------------------------------------------------------------*/ -static TEE_Result tee_ta_load(const kta_signed_header_t *signed_ta, - struct tee_ta_ctx **ta_ctx) +static TEE_Result tee_ta_load(const TEE_UUID *uuid, + const struct shdr *signed_ta, + struct tee_ta_ctx **ta_ctx) { - /* ta & ta_session is assumed to be != NULL from previous checks */ TEE_Result res; - size_t heap_size = 0; /* gcc warning */ + /* man_flags: mandatory flags */ + uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; + /* opt_flags: optional flags */ + uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS; struct tee_ta_ctx *ctx = NULL; - const uint8_t *nmem_ta; - kta_signed_header_t *sec_signed_ta = NULL; - ta_head_t *sec_head = NULL; + struct shdr *sec_shdr = NULL; + struct ta_head *ta_head; - res = tee_ta_load_header(signed_ta, &sec_signed_ta, &sec_head, - &nmem_ta); + res = tee_ta_load_header(signed_ta, &sec_shdr); if (res != TEE_SUCCESS) goto error_return; - res = tee_ta_load_check_head_integrity(sec_signed_ta, sec_head); + res = tee_ta_load_check_shdr(sec_shdr); if (res != TEE_SUCCESS) goto error_return; - free(sec_signed_ta); - sec_signed_ta = NULL; - /* * ------------------------------------------------------------------ @@ -626,57 +484,60 @@ static TEE_Result tee_ta_load(const kta_signed_header_t *signed_ta, TAILQ_INIT(&ctx->cryp_states); TAILQ_INIT(&ctx->objects); TAILQ_INIT(&ctx->storage_enums); - ctx->head = sec_head; #if defined(CFG_SE_API) ctx->se_service = NULL; #endif - /* by default NSec DDR: starts at TA function code. */ - ctx->mem_swap = (uintptr_t)(nmem_ta + sizeof(ta_head_t) + - sec_head->nbr_func * sizeof(ta_func_head_t)); + res = tee_ta_load_elf(ctx, sec_shdr, signed_ta); + if (res != TEE_SUCCESS) + goto error_return; - ctx->num_res_funcs = ctx->head->zi_size >> 20; - ctx->head->zi_size &= 0xfffff; - if (ctx->num_res_funcs > ctx->head->nbr_func) { - res = TEE_ERROR_BAD_FORMAT; + ctx->load_addr = tee_mmu_get_load_addr(ctx); + ta_head = (struct ta_head *)(vaddr_t)ctx->load_addr; + + if (memcmp(&ta_head->uuid, uuid, sizeof(TEE_UUID)) != 0) { + res = TEE_ERROR_SECURITY; goto error_return; } - res = tee_ta_load_user_ta(ctx, sec_head, nmem_ta, &heap_size); - if (res != TEE_SUCCESS) + /* check input flags bitmask consistency and save flags */ + if ((ta_head->flags & opt_flags) != ta_head->flags || + (ta_head->flags & man_flags) != man_flags) { + EMSG("TA flag issue: flags=%x opt=%X man=%X", + ta_head->flags, opt_flags, man_flags); + res = TEE_ERROR_BAD_FORMAT; goto error_return; + } + + ctx->flags = ta_head->flags; + ctx->uuid = ta_head->uuid; + ctx->open_session_func = ta_head->open_session; + ctx->close_session_func = ta_head->close_session; + ctx->invoke_command_func = ta_head->invoke_command; ctx->ref_count = 1; TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); *ta_ctx = ctx; - /* - * Note that the setup below will cause at least one page fault so it's - * important that the session is fully registered at this stage. - */ - tee_ta_load_init_user_ta(ctx, heap_size); - DMSG("Loaded TA at 0x%" PRIxPTR ", ro_size %u, rw_size %u, zi_size %u", - tee_mm_get_smem(ctx->mm), ctx->head->ro_size, - ctx->head->rw_size, ctx->head->zi_size); + DMSG("Loaded TA at 0x%" PRIxPTR, tee_mm_get_smem(ctx->mm)); DMSG("ELF load address 0x%x", ctx->load_addr); set_tee_rs(NULL); tee_mmu_set_ctx(NULL); /* end thread protection (multi-threaded) */ + free(sec_shdr); return TEE_SUCCESS; error_return: + free(sec_shdr); set_tee_rs(NULL); tee_mmu_set_ctx(NULL); if (ctx != NULL) { - if ((ctx->flags & TA_FLAG_USER_MODE) != 0) - tee_mmu_final(ctx); - tee_mm_free(ctx->mm_heap_stack); + tee_mmu_final(ctx); + tee_mm_free(ctx->mm_stack); tee_mm_free(ctx->mm); - /* If sec DDR was allocated for mem_swap free it */ - tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, ctx->mem_swap)); free(ctx); } return res; @@ -754,18 +615,12 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, struct abi_user32_param *usr_params; tee_paddr_t usr_stack; tee_uaddr_t stack_uaddr; - tee_uaddr_t start_uaddr; struct tee_ta_ctx *ctx = session->ctx; - ta_func_head_t *ta_func_head = (ta_func_head_t *)((vaddr_t)ctx->head + - sizeof(ta_head_t)); tee_uaddr_t params_uaddr; TEE_ErrorOrigin serr = TEE_ORIGIN_TEE; TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); - TEE_ASSERT((uint32_t) func <= - (ctx->head->nbr_func - ctx->num_res_funcs)); - /* Set timeout of entry */ tee_ta_set_invoke_timeout(session, cancel_req_to); @@ -778,7 +633,7 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, tee_ta_set_current_session(session); /* Make room for usr_params at top of stack */ - usr_stack = tee_mm_get_smem(ctx->mm_heap_stack) + ctx->stack_size; + usr_stack = tee_mm_get_smem(ctx->mm_stack) + ctx->stack_size; usr_stack -= sizeof(struct abi_user32_param); usr_params = (struct abi_user32_param *)usr_stack; abi_param_to_user32_param(usr_params, param->params, param->types); @@ -792,15 +647,13 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, if (res != TEE_SUCCESS) goto cleanup_return; - start_uaddr = ctx->load_addr + ta_func_head[func].start; - switch (func) { case USER_TA_FUNC_OPEN_CLIENT_SESSION: res = thread_enter_user_mode(param->types, params_uaddr, (vaddr_t)session, 0, stack_uaddr, - start_uaddr, &ctx->panicked, - &ctx->panic_code); + ctx->open_session_func, + &ctx->panicked, &ctx->panic_code); /* * According to GP spec the origin should allways be set to the @@ -811,7 +664,8 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, case USER_TA_FUNC_CLOSE_CLIENT_SESSION: res = thread_enter_user_mode((vaddr_t)session, 0, 0, 0, - stack_uaddr, start_uaddr, + stack_uaddr, + ctx->close_session_func, &ctx->panicked, &ctx->panic_code); serr = TEE_ORIGIN_TRUSTED_APP; @@ -820,8 +674,8 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, case USER_TA_FUNC_INVOKE_COMMAND: res = thread_enter_user_mode(cmd, param->types, params_uaddr, (vaddr_t)session, stack_uaddr, - start_uaddr, &ctx->panicked, - &ctx->panic_code); + ctx->invoke_command_func, + &ctx->panicked, &ctx->panic_code); serr = TEE_ORIGIN_TRUSTED_APP; break; @@ -868,7 +722,7 @@ cleanup_return: * Function is not thread safe */ static TEE_Result tee_ta_rpc_load(const TEE_UUID *uuid, - kta_signed_header_t **ta, + struct shdr **ta, uint32_t *handle, uint32_t *ret_orig) { @@ -969,10 +823,10 @@ static void tee_ta_destroy_context(struct tee_ta_ctx *ctx) } } - if (ctx->mm_heap_stack != NULL) { - pa = tee_mm_get_smem(ctx->mm_heap_stack); + if (ctx->mm_stack) { + pa = tee_mm_get_smem(ctx->mm_stack); if (tee_mmu_user_pa2va(ctx, pa, &va) == TEE_SUCCESS) { - s = tee_mm_get_bytes(ctx->mm_heap_stack); + s = tee_mm_get_bytes(ctx->mm_stack); memset(va, 0, s); cache_maintenance_l1(DCACHE_AREA_CLEAN, va, s); } @@ -994,17 +848,12 @@ static void tee_ta_destroy_context(struct tee_ta_ctx *ctx) &ctx->open_sessions, KERN_IDENTITY); } - - /* If TA was loaded in reserved DDR free the alloc. */ - tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, ctx->mem_swap)); - if ((ctx->flags & TA_FLAG_USER_MODE) != 0) { tee_mmu_final(ctx); - tee_mm_free(ctx->mm_heap_stack); + tee_mm_free(ctx->mm_stack); } if (ctx->static_ta == NULL) { tee_mm_free(ctx->mm); - free(ctx->head); } /* Free cryp states created by this TA */ @@ -1168,8 +1017,8 @@ static TEE_Result tee_ta_init_session_with_context(struct tee_ta_ctx *ctx, return TEE_ERROR_BUSY; DMSG(" ... Re-open TA %08x-%04x-%04x", - ctx->head->uuid.timeLow, - ctx->head->uuid.timeMid, ctx->head->uuid.timeHiAndVersion); + ctx->uuid.timeLow, + ctx->uuid.timeMid, ctx->uuid.timeHiAndVersion); ctx->ref_count++; @@ -1210,39 +1059,37 @@ static TEE_Result tee_ta_init_static_ta_session(const TEE_UUID *uuid, TAILQ_INIT(&ctx->open_sessions); TAILQ_INIT(&ctx->cryp_states); TAILQ_INIT(&ctx->objects); - ctx->num_res_funcs = 0; ctx->ref_count = 1; s->ctx = ctx; ctx->flags = TA_FLAG_MULTI_SESSION; - ctx->head = (ta_head_t *)ta; ctx->static_ta = ta; + ctx->uuid = ta->uuid; TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); DMSG(" %s : %08x-%04x-%04x", ctx->static_ta->name, - ctx->head->uuid.timeLow, - ctx->head->uuid.timeMid, - ctx->head->uuid.timeHiAndVersion); + ctx->uuid.timeLow, + ctx->uuid.timeMid, + ctx->uuid.timeHiAndVersion); return TEE_SUCCESS; } -static TEE_Result tee_ta_init_session_with_signed_ta( - const kta_signed_header_t *signed_ta, +static TEE_Result tee_ta_init_session_with_signed_ta(const TEE_UUID *uuid, + const struct shdr *signed_ta, struct tee_ta_session *s) { TEE_Result res; DMSG(" Load dynamic TA"); /* load and verify */ - res = tee_ta_load(signed_ta, &s->ctx); + res = tee_ta_load(uuid, signed_ta, &s->ctx); if (res != TEE_SUCCESS) return res; DMSG(" dyn TA : %08x-%04x-%04x", - s->ctx->head->uuid.timeLow, - s->ctx->head->uuid.timeMid, - s->ctx->head->uuid.timeHiAndVersion); + s->ctx->uuid.timeLow, s->ctx->uuid.timeMid, + s->ctx->uuid.timeHiAndVersion); return res; } @@ -1254,7 +1101,7 @@ static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, { TEE_Result res; struct tee_ta_ctx *ctx; - kta_signed_header_t *ta = NULL; + struct shdr *ta = NULL; uint32_t handle = 0; struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session)); @@ -1285,7 +1132,7 @@ static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, if (res != TEE_SUCCESS) goto out; - res = tee_ta_init_session_with_signed_ta(ta, s); + res = tee_ta_init_session_with_signed_ta(uuid, ta, s); /* * Free normal world shared memory now that the TA either has been * copied into secure memory or the TA failed to be initialized. @@ -1520,16 +1367,6 @@ TEE_Result tee_ta_get_client_id(TEE_Identity *id) return TEE_SUCCESS; } -uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx) -{ - if ((ctx->flags & TA_FLAG_EXEC_DDR) == 0) { - return tee_mm_get_smem(ctx->mm); - } else { - return tee_mmu_get_load_addr(ctx) + sizeof(ta_head_t) + - ctx->head->nbr_func * sizeof(ta_func_head_t); - } -} - TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, struct tee_ta_session_head *open_sessions) @@ -1614,19 +1451,17 @@ static void dump_state(struct tee_ta_ctx *ctx) char uuid[TEE_UUID_STRING_LEN]; bool active __unused; - uuid2str(uuid, &ctx->head->uuid); + uuid2str(uuid, &ctx->uuid); active = ((tee_ta_get_current_session(&s) == TEE_SUCCESS) && s && s->ctx == ctx); EMSG_RAW("Status of TA %s (%p)", uuid, (void *)ctx); EMSG_RAW("- load addr : 0x%x ctx-idr: %d %s", ctx->load_addr, ctx->context, active ? "(active)" : ""); - EMSG_RAW("- code area : 0x%" PRIxPTR " ro:%u rw:%u zi:%u", - tee_mm_get_smem(ctx->mm), ctx->head->ro_size, - ctx->head->rw_size, ctx->head->zi_size); - EMSG_RAW("- heap/stack: 0x%" PRIxPTR " stack:%zu", - tee_mm_get_smem(ctx->mm_heap_stack), - ctx->stack_size); + EMSG_RAW("- code area : 0x%" PRIxPTR " %zu", + tee_mm_get_smem(ctx->mm), tee_mm_get_bytes(ctx->mm)); + EMSG_RAW("- stack: 0x%" PRIxPTR " stack:%zu", + tee_mm_get_smem(ctx->mm_stack), ctx->stack_size); } void tee_ta_dump_current(void) diff --git a/core/arch/arm/mm/tee_mmu.c b/core/arch/arm/mm/tee_mmu.c index cf40c72b..1e301d7d 100644 --- a/core/arch/arm/mm/tee_mmu.c +++ b/core/arch/arm/mm/tee_mmu.c @@ -270,16 +270,16 @@ TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param) goto exit; /* - * Map heap and stack + * Map stack */ - smem = tee_mm_get_smem(ctx->mm_heap_stack); + smem = tee_mm_get_smem(ctx->mm_stack); if (core_va2pa((void *)smem, &pa)) { res = TEE_ERROR_SECURITY; goto exit; } tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_HEAP_STACK_IDX, CORE_MMU_USER_CODE_SIZE, - pa, tee_mm_get_bytes(ctx->mm_heap_stack), + pa, tee_mm_get_bytes(ctx->mm_stack), TEE_MMU_UDATA_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR); /* diff --git a/core/arch/arm/plat-hikey/conf.mk b/core/arch/arm/plat-hikey/conf.mk index abe840e4..906b9a51 100644 --- a/core/arch/arm/plat-hikey/conf.mk +++ b/core/arch/arm/plat-hikey/conf.mk @@ -20,7 +20,6 @@ CFG_SECURE_TIME_SOURCE_CNTPCT ?= y CFG_PL011 ?= y CFG_HWSUPP_MEM_PERM_PXN ?= y CFG_WITH_STACK_CANARIES ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= n CFG_GENERIC_BOOT ?= y CFG_PM_STUBS ?= y diff --git a/core/arch/arm/plat-mediatek/conf.mk b/core/arch/arm/plat-mediatek/conf.mk index 27c632ce..41b09fa5 100644 --- a/core/arch/arm/plat-mediatek/conf.mk +++ b/core/arch/arm/plat-mediatek/conf.mk @@ -20,7 +20,6 @@ CFG_SECURE_TIME_SOURCE_CNTPCT ?= y CFG_8250_UART ?= y CFG_HWSUPP_MEM_PERM_PXN ?= y CFG_WITH_STACK_CANARIES ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= n CFG_GENERIC_BOOT ?= y CFG_PM_STUBS ?= y diff --git a/core/arch/arm/plat-stm/conf.mk b/core/arch/arm/plat-stm/conf.mk index 9aea6c51..3efb9595 100644 --- a/core/arch/arm/plat-stm/conf.mk +++ b/core/arch/arm/plat-stm/conf.mk @@ -19,7 +19,6 @@ CFG_GENERIC_BOOT ?= y CFG_WITH_SOFTWARE_PRNG ?= n CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_MMU_V7_TTB ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_PL310_LOCKED ?= n CFG_TEE_GDB_BOOT ?= y CFG_BOOT_SYNC_CPU ?= y diff --git a/core/arch/arm/plat-sunxi/conf.mk b/core/arch/arm/plat-sunxi/conf.mk index 854fc643..fa8f5410 100644 --- a/core/arch/arm/plat-sunxi/conf.mk +++ b/core/arch/arm/plat-sunxi/conf.mk @@ -22,5 +22,4 @@ CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y core-platform-cppflags += -DTEE_USE_DLMALLOC core-platform-cppflags += -D_USE_SLAPORT_LIB -core-platform-cppflags += -DCFG_NO_TA_HASH_SIGN CFG_GIC := y diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk index f7760eff..c3a259cc 100644 --- a/core/arch/arm/plat-vexpress/conf.mk +++ b/core/arch/arm/plat-vexpress/conf.mk @@ -28,7 +28,6 @@ CFG_PM_STUBS := y CFG_GENERIC_BOOT := y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_TEE_FS_KEY_MANAGER_TEST := y -CFG_NO_TA_HASH_SIGN ?= y ifeq ($(PLATFORM_FLAVOR),juno) CFG_CRYPTO_SHA256_ARM32_CE ?= $(CFG_ARM32_core) diff --git a/core/core.mk b/core/core.mk index 3e38c257..01fecd6d 100644 --- a/core/core.mk +++ b/core/core.mk @@ -69,8 +69,16 @@ include mk/lib.mk # # Do main source # + subdirs = $(core-platform-subdirs) core include mk/subdir.mk + +# Generate C file to embed public key for TA verification +gen-srcs += core/ta_pub_key.c +$(out-dir)/core/ta_pub_key.c: $(TA_SIGN_KEY) + @$(cmd-echo-silent) ' GEN $@' + @$(q)scripts/pem_to_pub_c.py --prefix ta_pub_key --key $< --out $@ + include mk/compile.mk include $(platform-dir)/link.mk diff --git a/core/default_signing.properties b/core/default_signing.properties deleted file mode 100644 index fd6c7dbf..00000000 --- a/core/default_signing.properties +++ /dev/null @@ -1,11 +0,0 @@ -PAYLOAD_HASH_TYPE=SHA256_HASH -LOAD_ADDRESS=0x0 -START_ADDRESS=0x0 -DMA_FLAG=false -PKA_FLAG=false -BUFFER_SIZE=8k -SW_VERSION=0 -MAJOR_BUILD_VERSION=0 -MINOR_BUILD_VERSION=0 -FLAGS=0 -TRUSTED_APP_HASH_TYPE=SHA256_HASH diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h index a6af57bf..4d70a327 100644 --- a/core/include/kernel/tee_ta_manager.h +++ b/core/include/kernel/tee_ta_manager.h @@ -28,14 +28,10 @@ #ifndef TEE_TA_MANAGER_H #define TEE_TA_MANAGER_H +#include <tee_api_types.h> +#include <utee_types.h> #include <kernel/tee_common.h> - -#include "tee_api_types.h" -#include "tee_api_types.h" -#include "tee_ta.h" -#include <kernel/kta_types.h> -#include "tee_ta_manager_unpg.h" -#include "utee_types.h" +#include <kernel/tee_ta_manager_unpg.h> /* Magic TEE identity pointer: set when teecore requests a TA close */ #define KERN_IDENTITY ((TEE_Identity *)-1) @@ -99,11 +95,6 @@ void tee_ta_set_current_session(struct tee_ta_session *sess); TEE_Result tee_ta_get_client_id(TEE_Identity *id); -/* - * Get pointer of executable part of the TA located in virtual kernel memory - */ -uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx); - /* Returns OK is sess is a valid session pointer or static TA */ TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, struct tee_ta_session_head diff --git a/core/include/kernel/tee_ta_manager_unpg.h b/core/include/kernel/tee_ta_manager_unpg.h index 67e9a19c..33023d95 100644 --- a/core/include/kernel/tee_ta_manager_unpg.h +++ b/core/include/kernel/tee_ta_manager_unpg.h @@ -31,7 +31,6 @@ #include <types_ext.h> #include <kernel/tee_common_unpg.h> -#include <kernel/tee_ta.h> #include <mm/tee_mmu_types.h> #include <mm/tee_mm_unpg.h> #if defined(CFG_SE_API) @@ -49,6 +48,12 @@ TAILQ_HEAD(tee_storage_enum_head, tee_storage_enum); /* Context of a loaded TA */ struct tee_ta_ctx { + TEE_UUID uuid; + tee_uaddr_t open_session_func; + tee_uaddr_t close_session_func; + tee_uaddr_t invoke_command_func; + size_t stack_size; /* size of stack */ + uint32_t flags; /* TA_FLAGS from TA header */ TAILQ_ENTRY(tee_ta_ctx) link; /* list of sessions opened by this TA */ struct tee_ta_session_head open_sessions; @@ -58,16 +63,11 @@ struct tee_ta_ctx { struct tee_obj_head objects; /* List of storage enumerators opened by this TA */ struct tee_storage_enum_head storage_enums; - ta_head_t *head; /* ptr to the ta head in secure memory */ - uintptr_t mem_swap; /* ptr to code and data in memory swap */ tee_mm_entry_t *mm; /* secure world memory */ - tee_mm_entry_t *mm_heap_stack; /* shared section of heap and stack */ - size_t stack_size; /* size of stack */ + tee_mm_entry_t *mm_stack;/* stack */ uint32_t load_addr; /* elf load addr (from TAs address space) */ uint32_t context; /* Context ID of the process */ struct tee_mmu_info *mmu; /* Saved MMU information (ddr only) */ - uint32_t num_res_funcs; /* number of reserved ta_func_head_t (2 or 0) */ - uint32_t flags; /* TA_FLAGS from sub header */ uint32_t panicked; /* True if TA has panicked, written from asm */ uint32_t panic_code; /* Code supplied for panic */ uint32_t ref_count; /* Reference counter for multi session TA */ diff --git a/core/include/signed_hdr.h b/core/include/signed_hdr.h new file mode 100644 index 00000000..01a329da --- /dev/null +++ b/core/include/signed_hdr.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SIGNED_HDR_H +#define SIGNED_HDR_H + +#include <types_ext.h> + +enum shdr_img_type { + SHDR_TA = 0, +}; + +#define SHDR_MAGIC 0x4f545348 + +/** + * struct shdr - signed header + * @magic: magic number must match SHDR_MAGIC + * @img_type: image type, values defined by enum shdr_img_type + * @img_size: image size in bytes + * @algo: algorithm, defined by public key algorithms TEE_ALG_* + * from TEE Internal API specification + * @hash_size: size of the signed hash + * @sig_size: size of the signature + * @hash: hash of an image + * @sig: signature of @hash + */ +struct shdr { + uint32_t magic; + uint32_t img_type; + uint32_t img_size; + uint32_t algo; + uint16_t hash_size; + uint16_t sig_size; + /* + * Commented out element used to visualize the layout dynamic part + * of the struct. + * + * hash is accessed through the macro SHDR_GET_HASH and + * signature is accessed through the macro SHDR_GET_SIG + * + * uint8_t hash[hash_size]; + * uint8_t sig[sig_size]; + */ +}; + +#define SHDR_GET_SIZE(x) (sizeof(struct shdr) + (x)->hash_size + \ + (x)->sig_size) +#define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1) +#define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size) + +#endif /*SIGNED_HDR_H*/ + diff --git a/core/include/kernel/tee_ta.h b/core/include/ta_pub_key.h index a25dde91..d6ad73a3 100644 --- a/core/include/kernel/tee_ta.h +++ b/core/include/ta_pub_key.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,54 +24,14 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef KERNEL_TA_PUB_KEY_H +#define KERNEL_TA_PUB_KEY_H -#ifndef TEE_TA_H -#define TEE_TA_H +#include <types_ext.h> -#include <stdint.h> -#include <tee_api_types.h> +extern const uint32_t ta_pub_key_exponent; +extern const uint8_t ta_pub_key_modulus[]; +extern const size_t ta_pub_key_modulus_size; -#define TA_HASH_SIZE 32 -#define TA_UUID_CLOCK_SIZE 8 -#define TA_SIGNATURE_SIZE 264 +#endif /*KERNEL_TA_PUB_KEY_H*/ -#define TA_HEAD_FLAG_MASK 0xFFF00000UL -#define TA_HEAD_GOT_MASK 0xFFFFUL - -/* Trusted Application header */ -typedef struct { - TEE_UUID uuid; - uint32_t nbr_func; - uint32_t ro_size; - uint32_t rw_size; - uint32_t zi_size; - uint32_t rel_dyn_got_size; - uint32_t hash_type; - /* uint32_t prop_tracelevel; */ -} ta_head_t; - -struct ta_rel_dyn { - uint32_t addr; - uint32_t info; -}; - -/*----------------------------------------------------------------------------- - signed header - ta_head_t - ta_func_head_t (1) - ta_func_head_t (2) - ... - ta_func_head_t (N) N = ta_head(_t).nbr_func - func_1 - func_1 - ... - func_N - GOT - find_service_addr - hash_1 - hash_2 - ... - hash_M - *---------------------------------------------------------------------------*/ - -#endif diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c index f15f7389..3a867f1c 100644 --- a/core/tee/tee_svc.c +++ b/core/tee/tee_svc.c @@ -260,7 +260,7 @@ TEE_Result tee_svc_sys_get_property(uint32_t prop, tee_uaddr_t buf, size_t blen) if (blen < sizeof(TEE_UUID)) return TEE_ERROR_SHORT_BUFFER; return tee_svc_copy_to_user(sess, (void *)buf, - &sess->ctx->head->uuid, + &sess->ctx->uuid, sizeof(TEE_UUID)); default: if (blen < tee_props_lut[prop].len) @@ -454,6 +454,7 @@ static TEE_Result tee_svc_update_out_param( (called_sess->ctx->static_ta != NULL) || ((called_sess->ctx->flags & TA_FLAG_USER_MODE) != 0); + tee_ta_set_current_session(sess); abi_user32_param_to_param(callee_params, usr_param, param->types); @@ -550,7 +551,7 @@ TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest, goto function_exit; clnt_id->login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id->uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id->uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, NULL, param_types, usr_param, param, tmp_buf_pa, &mm_param); @@ -609,7 +610,7 @@ TEE_Result tee_svc_close_ta_session(TEE_TASessionHandle ta_sess) return res; clnt_id.login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id.uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); tee_ta_set_current_session(NULL); res = tee_ta_close_session((struct tee_ta_session *)ta_sess, @@ -645,7 +646,7 @@ TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle ta_sess, return res; clnt_id.login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id.uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, called_sess, param_types, usr_param, ¶m, tmp_buf_pa, &mm_param); @@ -887,8 +888,7 @@ TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *mytime) res = tee_time_get_sys_time(&t); break; case UTEE_TIME_CAT_TA_PERSISTENT: - res = tee_time_get_ta_time((const void *)&s->ctx->head->uuid, - &t); + res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t); break; case UTEE_TIME_CAT_REE: res = tee_time_get_ree_time(&t); @@ -921,7 +921,7 @@ TEE_Result tee_svc_set_ta_time(const TEE_Time *mytime) if (res != TEE_SUCCESS) return res; - return tee_time_set_ta_time((const void *)&s->ctx->head->uuid, &t); + return tee_time_set_ta_time((const void *)&s->ctx->uuid, &t); } #ifdef CFG_CACHE_API diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c index 45c722a4..26f3ad81 100644 --- a/core/tee/tee_svc_storage.c +++ b/core/tee/tee_svc_storage.c @@ -110,7 +110,7 @@ static char *tee_svc_storage_create_filename(struct tee_ta_session *sess, if (file == NULL) return NULL; - pos = tee_b2hs((uint8_t *)&sess->ctx->head->uuid, file, + pos = tee_b2hs((uint8_t *)&sess->ctx->uuid, file, sizeof(TEE_UUID), hslen); file[pos] = '/'; pos++; @@ -136,7 +136,7 @@ static char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) if (dir == NULL) return NULL; - tee_b2hs((uint8_t *)&sess->ctx->head->uuid, dir, sizeof(TEE_UUID), + tee_b2hs((uint8_t *)&sess->ctx->uuid, dir, sizeof(TEE_UUID), hslen); return (char *)dir; @@ -434,7 +434,7 @@ TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id, if (res != TEE_SUCCESS) goto exit; - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, flags, &po); if (res != TEE_SUCCESS) goto exit; @@ -543,7 +543,7 @@ TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id, if (res != TEE_SUCCESS) goto err; - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, flags, &po); if (res != TEE_SUCCESS) goto err; @@ -766,7 +766,7 @@ TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id, } /* reserve dest name */ - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po); if (res != TEE_SUCCESS) goto exit; diff --git a/documentation/build_system.md b/documentation/build_system.md index 181380c1..035e27ca 100644 --- a/documentation/build_system.md +++ b/documentation/build_system.md @@ -81,7 +81,7 @@ contains: - In `include/`: header files for the above libraries - In `mk/`: **ta_dev_kit.mk**, which is a Make include file with suitable rules to build a TA, and its dependencies - - `scripts/fix_ta_binary`: a Perl script used by ta_dev_kit.mk. + - `scripts/sign.py`: a Python script used by ta_dev_kit.mk to sign TAs. - In `src`: **user_ta_header.c** and **user_ta_elf_arm.lds**: source file and linker script to add a suitable header to the Trusted Application (as expected by the loader code in the TEE Core) diff --git a/documentation/optee_design.md b/documentation/optee_design.md index 90d509a0..a7a63b08 100644 --- a/documentation/optee_design.md +++ b/documentation/optee_design.md @@ -505,7 +505,31 @@ layer allows for replacing the default implementation, as explained in Will be written soon. # 11. Trusted Applications -Will be written soon. +## Format +Trusted Applications consists of a signed ELF file. + +The format a TA is: +``` +<Signed header> +<ELF> +``` + +Where `<ELF>` is the content of a standard ELF file and `<Signed header>` +consists of: + +| Type | Name | Comment | +|------|------|---------| +| `uint32_t` | magic | Holds the magic number `0x4f545348` | +| `uint32_t` | img_type | image type, values defined by enum shdr_img_type | +| `uint32_t` | img_size | image size in bytes | +| `uint32_t` | algo | algorithm, defined by public key algorithms `TEE_ALG_*` from TEE Internal API specification | +| `uint16_t` | hash_size | size of the signed hash | +| `uint16_t` | sig_size | size of the signature | +| `uint8_t[hash_size]` | hash | Hash of the fields above and the `<ELF>` above | +| `uint8_t[sig_size]` | signature | Signature of hash | + + +## Will be written soon. ### Initialize context ### Open Session ### Invoke command diff --git a/keys/default_ta.pem b/keys/default_ta.pem new file mode 100644 index 00000000..a8e5dcdf --- /dev/null +++ b/keys/default_ta.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAploYrcCzzuMMkCt9QJusu1pJiEIKseCSwIaR5p7voOHxL5D2 +Zt3qFVrAKLSd31IMbqXGGUOsaajyX/5gAKXSOswSAfNbugxRHCz0sHe51nI1HA9z +zS8W+bqJhKCbv4tbf+iLi5/IceocbB8AoO7KPr8YjlebSGbri9RAUa6GoYb40Av6 +ti4lLgX/dgFG1z3rH3z83x6Ci16wyqPqFr4tblRQnLhB7xfHf2BUqvlwoPiYLoL5 +jF/7nIiOd7Aycpka4ARevx2q9/AFPLSV3U26OnGh+HKOHZjjE7rKsCe/h1lUJ/jo +7MaFN9I6leSlCZrQH6OGsJLYAh4zddsmvyf8NQIDAQABAoIBAEoooBfVcFMqpM8g +lBXZUIe1GFLGHj5t/v4U/7Xv5KO0FfE+jpoNE+2xJzj+S+LikOhCvq1Enff8eRCS +NfoT8kSD9QMpmhq2ovIMmIiS1yXihAqeWOF/vJ5XqjaV4tjhJ0k+Qfdco98knscU +ixMzYLXYOvo509/TAe60EHhZdWtMKCmHqvFBRDhYFF+HUxWnJa39G1u828ljv8uN +iRCXbEjoaWDwBJWRzDZJehrkQc2gQAkFpyePVqA3wm1tx1ZHEVwCqYOXOP49/LAc +rQfoWUpm4chjEHnZEb+dQxa3N8Qeq2lqgcqrOX8NIfpzWTWQ1JM+ksinQwMJ0BDV ++Lf1nAECgYEA2KBBtsj41ITez8iA0DpXovH1F9oU9aJ9JKopNos8zIZg012bE5Ib +kFII0LiBGKLUP2PepTsPDIOxibLQDojg1aBGHISZVp/y81B4Rk7Wwg206ZQ848dM +AhACIrzOtJLoVEZTPf7C5QrNMhViyf2c8vFBjfTuM7Ze6a0fsvfJ2ikCgYEAxJaO +XKnOgKoG1Fe9JVM01U+260BEybNUbbXQCnvMjTSZCsOEmST9mhXhC56lhCNqmynt +FxNuq/JMwtS3TRhrYCPPCLFly+JNTqUS1mLQ9ytVbaw6fp9mSxFUQE9d9obkGwJC +3uXEx+bc7YSGuwD34wikX0tB1zzGIXRH2JlB6y0CgYEAgFlDVjdxJwmqslXL7JQE +xKizXPR7oqYpm4WucYDB/zRHPjSh41CYQEQ6sOAArUYcl4pmqmN5oSKOGFX37ASx +oiEaKV9vMuIGIp+1A4NGvyc734FTKmo04Kv3d/mCR38bZINeYscFVou11EzTgXZg +fZjwDFnooH8XcUCAHZuu3zECgYEAt6pltSMcgE7Z9JdIas/TI5vHLQEtgzhdH+bm +SHUjRaWnekvy3VWW7deVGtMMlmi0V+US0iVgl5rXposv+gJfh0HNUrTSg2qZiWlm +MQ+/Zb2BoeZv/A8Wdfnpue+svP+Hq8gwC6mlcJI7RFk1uw8LiXxwfWuFRv9LqMPH +wBBnar0CgYAJF3ukzm7rnut19lzS4r1uEIuuPwk/DjEkkil7U9wE5fr+ds5rCtXj +9591DLHrtE/CBOWym2+tIDr7OnmfU+934524mtLWVZdf39/DFM9Fc1VaSualrj/1 +BOLhBb7MEZqN7hHcQP7+49YW72GgX3pm0Ov5ke33FzN3ubIwAS6T7A== +-----END RSA PRIVATE KEY----- diff --git a/lib/libutee/arch/arm/user_ta_entry.c b/lib/libutee/arch/arm/user_ta_entry.c index 548752c2..98bafbc8 100644 --- a/lib/libutee/arch/arm/user_ta_entry.c +++ b/lib/libutee/arch/arm/user_ta_entry.c @@ -37,8 +37,6 @@ #include <tee_arith_internal.h> #include <malloc.h> -/* From user_ta_header.c, built within TA */ -extern const size_t ta_data_size; /* Exported to user_ta_header.c, built within TA */ @@ -64,7 +62,9 @@ TAILQ_HEAD_INITIALIZER(ta_sessions); static uint32_t ta_ref_count; static bool context_init; -extern uint8_t *ta_heap_base; +/* From user_ta_header.c, built within TA */ +extern uint8_t ta_heap[]; +extern const size_t ta_heap_size; uint32_t ta_param_types; TEE_Param ta_params[TEE_NUM_PARAMS]; @@ -102,7 +102,7 @@ static TEE_Result ta_header_add_session(uint32_t session_id) if (!context_init) { trace_set_level(tahead_get_trace_level()); - malloc_init(ta_heap_base, ta_data_size); + malloc_init(ta_heap, ta_heap_size); _TEE_MathAPI_Init(); context_init = true; } diff --git a/lib/libutee/include/user_ta_header.h b/lib/libutee/include/user_ta_header.h index c38d13d1..cc7061ab 100644 --- a/lib/libutee/include/user_ta_header.h +++ b/lib/libutee/include/user_ta_header.h @@ -30,60 +30,6 @@ #include <tee_api_types.h> -/* - * The generic format of a TA header. - * - * signed_header - * ta_head_t - * ta_func_head_t (1) - * ta_func_head_t (2) - * ... - * ta_func_head_t (N) N = ta_head(_t).nbr_func - * func_1 - * func_1 - * ... - * func_N - * hash_1 - * hash_2 - * ... - * hash_M - * - * The currently this format is limited to N = 5, resulting in a TA header as - * - * signed_header - * struct user_ta_head - * struct user_ta_func_head (1) - * struct user_ta_func_head (2) - * struct user_ta_func_head (3) - * struct user_ta_sub_head - * - * Note that the last two func heads are replaced by struct user_ta_sub_head. - */ - -struct user_ta_head { - TEE_UUID uuid; - uint32_t nbr_func; - uint32_t ro_size; - uint32_t rw_size; - uint32_t zi_size; - uint32_t got_size; - uint32_t hash_type; -}; - -#define USER_TA_HEAD_FLAG_USER_MODE 0x80000000UL -#define USER_TA_HEAD_FLAG_DDR_EXEC 0x40000000UL - -struct user_ta_func_head { - uint32_t cmd_id; - uint32_t start; /* offset to start func */ -}; - -struct user_ta_sub_head { - uint32_t flags; - uint32_t spare; - uint32_t heap_size; - uint32_t stack_size; -}; #define TA_FLAG_USER_MODE (1 << 0) #define TA_FLAG_EXEC_DDR (1 << 1) @@ -98,6 +44,15 @@ struct user_ta_sub_head { #define TA_FLAG_REMAP_SUPPORT (1 << 6) /* use map/unmap syscalls */ #define TA_FLAG_CACHE_MAINTENANCE (1 << 7) /* use cache flush syscall */ +struct ta_head { + TEE_UUID uuid; + uint32_t stack_size; + uint32_t flags; + uint32_t open_session; + uint32_t close_session; + uint32_t invoke_command; +}; + #define TA_PROP_STR_SINGLE_INSTANCE "gpd.ta.singleInstance" #define TA_PROP_STR_MULTI_SESSION "gpd.ta.multiSession" #define TA_PROP_STR_KEEP_ALIVE "gpd.ta.instanceKeepAlive" diff --git a/mk/cleanvars.mk b/mk/cleanvars.mk index abbdfee9..cba4db18 100644 --- a/mk/cleanvars.mk +++ b/mk/cleanvars.mk @@ -1,5 +1,6 @@ # Cleans all output variables from other make files to allow for a new start +gen-srcs := srcs := objs := libfiles := diff --git a/mk/compile.mk b/mk/compile.mk index 44748de5..d085c6ef 100644 --- a/mk/compile.mk +++ b/mk/compile.mk @@ -141,4 +141,8 @@ endef $(foreach f, $(srcs), $(eval $(call \ process_srcs,$(f),$(out-dir)/$(base-prefix)$$(basename $f).o))) +# Handle generated source files, that is, files that are compiled from out-dir +$(foreach f, $(gen-srcs), $(eval $(call \ + process_srcs,$(out-dir)/$(f),$(out-dir)/$(base-prefix)$$(basename $f).o))) + $(objs): $(conf-file) diff --git a/mk/config.mk b/mk/config.mk index 64662670..55e64150 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -84,3 +84,6 @@ CFG_TEE_FW_MANUFACTURER ?= FW_MAN_UNDEF # Encrypted File System Support CFG_ENC_FS ?= y + +# Embed public part of this key in OP-TEE OS +TA_SIGN_KEY ?= keys/default_ta.pem diff --git a/scripts/pem_to_pub_c.py b/scripts/pem_to_pub_c.py new file mode 100755 index 00000000..47c004da --- /dev/null +++ b/scripts/pem_to_pub_c.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015, Linaro Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('--prefix', required=True, \ + help='Prefix for the public key exponent and modulus in c file') + + parser.add_argument('--out', required=True, \ + help='Name of c file for the public key') + + parser.add_argument('--key', required=True, help='Name of key file') + + return parser.parse_args() + +def main(): + import array + from Crypto.PublicKey import RSA + from Crypto.Util.number import long_to_bytes + + args = get_args(); + + f = open(args.key, 'r') + key = RSA.importKey(f.read()) + f.close + + f = open(args.out, 'w') + + f.write("#include <stdint.h>\n"); + f.write("#include <stddef.h>\n\n"); + + f.write("const uint32_t " + args.prefix + "_exponent = " + + str(key.publickey().e) + ";\n\n") + + f.write("const uint8_t " + args.prefix + "_modulus[] = {\n") + i = 0; + for x in array.array("B", long_to_bytes(key.publickey().n)): + f.write("0x" + '{0:02x}'.format(x) + ",") + i = i + 1; + if i % 8 == 0: + f.write("\n"); + else: + f.write(" "); + f.write("};\n"); + + f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + \ + args.prefix + "_modulus);\n") + + f.close() + +if __name__ == "__main__": + main() diff --git a/scripts/sign.py b/scripts/sign.py new file mode 100755 index 00000000..f407f3be --- /dev/null +++ b/scripts/sign.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015, Linaro Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +def get_args(): + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument('--key', required=True, help='Name of key file') + parser.add_argument('--in', required=True, dest='inf', \ + help='Name of in file') + parser.add_argument('--out', required=True, help='Name of out file') + return parser.parse_args() + +def main(): + from Crypto.Signature import PKCS1_v1_5 + from Crypto.Hash import SHA256 + from Crypto.PublicKey import RSA + import struct + + args = get_args() + + f = open(args.key, 'rb') + key = RSA.importKey(f.read()) + f.close() + + f = open(args.inf, 'rb') + img = f.read() + f.close() + + signer = PKCS1_v1_5.new(key) + h = SHA256.new() + + digest_len = h.digest_size + sig_len = len(signer.sign(h)) + img_size = len(img) + + magic = 0x4f545348 # SHDR_MAGIC + img_type = 0 # SHDR_TA + algo = 0x70004830 # TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 + shdr = struct.pack('<IIIIHH', \ + magic, img_type, img_size, algo, digest_len, sig_len) + + h.update(shdr) + h.update(img) + sig = signer.sign(h) + + f = open(args.out, 'wb') + f.write(shdr) + f.write(h.digest()) + f.write(sig) + f.write(img) + f.close() + +if __name__ == "__main__": + main() diff --git a/ta/arch/arm/fix_ta_binary b/ta/arch/arm/fix_ta_binary deleted file mode 100755 index 51f2307c..00000000 --- a/ta/arch/arm/fix_ta_binary +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env perl -# Copyright (c) 2014, STMicroelectronics International N.V. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -use strict; -use warnings; -use diagnostics; -use Env qw($READELF $CROSS_COMPILE_user_ta); - -sub usage -{ - print STDERR "usage: $0 [-v] <elf> <binary>\n"; - exit(1); -} - -usage if ($#ARGV < 1); - -my $verbose = 0; - -if ($ARGV[0] =~ m/^-v$/) { - $verbose = 1; - shift @ARGV; -} - -usage if ($#ARGV != 1); -my ($elf, $bin) = @ARGV; - -open(BIN, "+<$bin") || die("Error opening TA file $bin"); -binmode(BIN); - -my $readelf = "readelf"; - -# In some build environments $READELF is not defined. -# As a 2nd alternative we use the environment variable $CROSS_COMPILE_user_ta -# to target the correct "readelf" - -if ($READELF) { - $readelf = $READELF -} -elsif ($CROSS_COMPILE_user_ta) { - $readelf = "${CROSS_COMPILE_user_ta}readelf" -} - -my $readelfcmd = "$readelf -s -W $elf"; -print "$readelfcmd\n" if ($verbose); -open(ELF, "$readelfcmd|") || die "Error exec $readelfcmd"; - -my $offs_0x14; -my $offs_0x14sym = "linker_RO_sections_size"; -my $offs_0x18; -my $offs_0x18sym = "linker_RW_sections_size"; -my $offs_0x1c; -my $offs_0x1csym = "linker_res_funcs_ZI_sections_size"; -my $offs_0x20; -my $offs_0x20sym = "linker_rel_dyn_GOT"; - -sub read_value -{ - my @args = split; - my $value = $args[1]; - return $value; -} - -while (<ELF>) { - last if defined $offs_0x14 && defined $offs_0x18 && - defined $offs_0x1c && defined $offs_0x20; - #print "Got $_"; - my @line = split; - my $line_elems = @line; - if ($line_elems > 6 && $line[6] =~ m/^ABS$/) { - if ($_ =~ m/$offs_0x14sym/) { - $offs_0x14 = read_value($_); - } elsif ($_ =~ m/$offs_0x18sym/) { - $offs_0x18 = read_value($_); - } elsif ($_ =~ m/$offs_0x1csym/) { - $offs_0x1c = read_value($_); - } elsif ($_ =~ m/$offs_0x20sym/) { - $offs_0x20 = read_value($_); - } - } -} - -die "Didn't find required symbol $offs_0x14sym in $elf" - unless defined $offs_0x14; -die "Didn't find required symbol $offs_0x18sym in $elf" - unless defined $offs_0x18; -die "Didn't find required symbol $offs_0x1csym in $elf" - unless defined $offs_0x1c; -die "Didn't find required symbol $offs_0x20sym in $elf" - unless defined $offs_0x20; - -sub write_value -{ - my ($val, $offs, $sym) = @_; - printf("%s = 0x%08x offset 0x%x\n", $sym, $val, $offs) if $verbose; - my $b = pack( 'V', $val); - seek(BIN, $offs, 0) || die "Couldn't seek to $_[1]: $!\n"; - syswrite(BIN, $b, 4) || die "$!"; -} - -write_value(hex $offs_0x14, 0x14, $offs_0x14sym); -write_value(hex $offs_0x18, 0x18, $offs_0x18sym); -write_value(hex $offs_0x1c, 0x1c, $offs_0x1csym); -write_value(hex $offs_0x20, 0x20, $offs_0x20sym); - -close(BIN); -close(ELF); -exit; - diff --git a/ta/arch/arm/link.mk b/ta/arch/arm/link.mk index f3a7fb4a..abc89c5a 100644 --- a/ta/arch/arm/link.mk +++ b/ta/arch/arm/link.mk @@ -3,14 +3,14 @@ link-out-dir = $(out-dir) link-script = $(TA_DEV_KIT_DIR)/src/user_ta_elf_arm.lds link-script-pp = $(link-out-dir)/ta.lds -FIX_TA_BINARY = $(TA_DEV_KIT_DIR)/scripts/fix_ta_binary - +SIGN = $(TA_DEV_KIT_DIR)/scripts/sign.py +TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem all: $(link-out-dir)/$(binary).elf $(link-out-dir)/$(binary).dmp \ - $(link-out-dir)/$(binary).bin + $(link-out-dir)/$(binary).stripped.elf $(link-out-dir)/$(binary).ta cleanfiles += $(link-out-dir)/$(binary).elf $(link-out-dir)/$(binary).dmp cleanfiles += $(link-out-dir)/$(binary).map -cleanfiles += $(link-out-dir)/$(binary).bin +cleanfiles += $(link-out-dir)/$(binary).stripped.elf cleanfiles += $(link-out-dir)/$(binary).ta cleanfiles += $(link-script-pp) @@ -27,13 +27,11 @@ link-ldadd += $(addprefix -L,$(libdirs)) link-ldadd += $(addprefix -l,$(call reverse,$(libnames))) ldargs-$(binary).elf := $(link-ldflags) $(objs) $(link-ldadd) - $(link-script-pp): $(link-script) $(MAKEFILE_LIST) @$(cmd-echo-silent) ' CP $@' $(q)mkdir -p $(dir $@) $(q)cp $< $@ - $(link-out-dir)/$(binary).elf: $(objs) $(libdeps) $(link-script-pp) @$(cmd-echo-silent) ' LD $@' $(q)$(LD$(sm)) $(ldargs-$(binary).elf) -o $@ @@ -42,7 +40,11 @@ $(link-out-dir)/$(binary).dmp: $(link-out-dir)/$(binary).elf @$(cmd-echo-silent) ' OBJDUMP $@' $(q)$(OBJDUMP$(sm)) -l -x -d $< > $@ -$(link-out-dir)/$(binary).bin: $(link-out-dir)/$(binary).elf +$(link-out-dir)/$(binary).stripped.elf: $(link-out-dir)/$(binary).elf @$(cmd-echo-silent) ' OBJCOPY $@' - $(q)$(OBJCOPY$(sm)) -O binary $< $@ - $(q)$(FIX_TA_BINARY) $< $@ + $(q)$(OBJCOPY$(sm)) --strip-unneeded $< $@ + +$(link-out-dir)/$(binary).ta: $(link-out-dir)/$(binary).stripped.elf \ + $(TA_SIGN_KEY) + @echo ' SIGN $@' + $(q)$(SIGN) --key $(TA_SIGN_KEY) --in $< --out $@ diff --git a/ta/arch/arm/user_ta_elf_arm.lds b/ta/arch/arm/user_ta_elf_arm.lds index e280e341..a7798231 100644 --- a/ta/arch/arm/user_ta_elf_arm.lds +++ b/ta/arch/arm/user_ta_elf_arm.lds @@ -1,153 +1,80 @@ OUTPUT_FORMAT("elf32-littlearm") OUTPUT_ARCH(arm) -/* The format of the TA binary should be - * - * ta_head - * ta_func_head - * RO Sections - * RW Sections - * ZI Sections - */ - -SECTIONS -{ - .ta_head : {*(.ta_head)} - .ta_func_head : {*(.ta_func_head)} - - /* RO sections */ - - start_of_RO_sections = .; - - /*. = 0x00100000 */ /* uTA runs in vmem at 1st MiB */ - .text : - { - *(.text .text.*) - *(.stub) - - /* ARM glue code for ARM and thumb */ - *(.glue_7) - *(.glue_7t) - - /* - * The below input sections should not be of use, but put - * in this output section to define their position. - */ - - /* Workaround for an erratum in ARM's VFP11 coprocessor */ - *(.vfp11_veneer) - /* ARMv4 interworking compatibility */ - *(.v4_bx) - /* GCC/ld specific */ - *(.gnu.linkonce.t.*) - *(.gnu.linkonce.r.*) - *(.gnu.warning) - *(.gcc_except_table) - } - .rodata : ALIGN(4) - { - *(.rodata .rodata.*) - *(.rodata1) - . = ALIGN(4); - } - .rel.dyn : - { - start_of_rel_data_section = .; - *(.rel.data) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - end_of_rel_data_section = .; - start_of_rela_data_section = .; - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - end_of_rela_data_section = .; - } - - . = ALIGN(4); - end_of_RO_sections = .; - - /* RW sections */ - - start_of_RW_sections = .; - start_of_GOT_sections = .; - - .data : ALIGN(4) - { - *(.got.*) - *(.got) - end_of_GOT_sections = .; - - *(.ta_heap_base) - - *(.data .data.*) - /* GCC/ld specific */ - *(.gnu.linkonce.d.*) - } - .data1 : {*(.data1)} - .tdata : {*(.tdata .tdata.*)} - - end_of_RW_sections = .; - - /* ZI sections */ - - start_of_ZI_sections = .; - - .bss : ALIGN(4) - { - *(.dynbss) - *(.bss .bss.*) - /* GCC/ld specific */ - *(.gnu.linkonce.b.*) - } - .tbss : {*(.tbss .tbss.*)} - - end_of_ZI_sections = .; - - .interp ALIGN(4) : { *(.interp) } - .hash ALIGN(4) : { *(.hash) } - .dynsym ALIGN(4) : { *(.dynsym) } - .dynstr ALIGN(4) : { *(.dynstr) } - .gnu.version ALIGN(4) : { *(.gnu.version) } - .gnu.version_d ALIGN(4) : { *(.gnu.version_d) } - .gnu.version_r ALIGN(4) : { *(.gnu.version_r) } - .dynamic ALIGN(4) : { *(.dynamic) } - - /* Stabs debugging sections. */ - .stab : { *(.stab) } - .stabstr : { *(.stabstr) } - .stab.excl : { *(.stab.excl) } - .stab.exclstr : { *(.stab.exclstr) } - .stab.index : { *(.stab.index) } - .stab.indexstr : { *(.stab.indexstr) } - .comment : { *(.comment) } - - /* - * Remove relocation information for GOT and the headers. - * All needed relocation informtion should already be matched above. - */ - .junkedrel /*ALIGN(4)*/ : - { - *(.rel.*) - *(.rela.*) - } - - PROVIDE(linker_RO_sections_size = end_of_RO_sections - start_of_RO_sections); - - linker_RW_sections_size = end_of_RW_sections - start_of_RW_sections; - - ZI_sections_size = end_of_ZI_sections - start_of_ZI_sections; - ASSERT(ZI_sections_size <= 0xfffff, "Too large ZI_sections_size") - /* - * Reserve the last two struct user_ta_func_head elements for the - * properties - */ - linker_res_funcs_ZI_sections_size = (2 << 20) + ZI_sections_size; - - GOT_sections_size = end_of_GOT_sections - start_of_GOT_sections; - rel_sections_size = end_of_rel_data_section - start_of_rel_data_section; - rela_sections_size = end_of_rela_data_section - start_of_rela_data_section; - ASSERT(rela_sections_size == 0, "Can't handle nonzero rela_sections_size") - ASSERT(GOT_sections_size <= 0xffff, "Too large GOT_sections_size") - ASSERT(rel_sections_size <= 0xffff, "Too large rel_sections_size") - linker_rel_dyn_GOT = (rel_sections_size << 16) + GOT_sections_size; +PHDRS { + rodata PT_LOAD; + rwdata PT_LOAD; + rodata2 PT_LOAD; + dyn PT_DYNAMIC; +} +SECTIONS { + .ta_head : {*(.ta_head)} :rodata + + .text : { + *(.text .text.*) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + /* Workaround for an erratum in ARM's VFP11 coprocessor */ + *(.vfp11_veneer) + } + .eh_frame : { *(.eh_frame) } + .rodata : { + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) + } + /* .ARM.exidx is sorted, so has to go in its own output section. */ + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .plt : { *(.plt) } + .got : { *(.got.plt) *(.got) } + + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.dyn : { *(.rel.dyn) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + /* Page align to allow dropping execute bit for RW data */ + . = ALIGN(4096); + + .data : { *(.data .data.* .gnu.linkonce.d.*) } :rwdata + + .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) } + + /* Page align to separate from RW data */ + . = ALIGN(4096); + + .dynamic : { *(.dynamic) } :dyn :rodata2 + .dynsym : { *(.dynsym) } :rodata2 + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + + /DISCARD/ : { *(.interp) } + + linker_RO_sections_size = 12; + linker_RW_sections_size = 12; + linker_res_funcs_ZI_sections_size = 12; + linker_rel_dyn_GOT = 12; } diff --git a/ta/arch/arm/user_ta_header.c b/ta/arch/arm/user_ta_header.c index 034443f2..b5f211ad 100644 --- a/ta/arch/arm/user_ta_header.c +++ b/ta/arch/arm/user_ta_header.c @@ -58,42 +58,19 @@ void ta_entry_invoke_command(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], uint32_t session_id) __noreturn; -/* These externs are defined in the ld link script */ -extern uint32_t linker_RO_sections_size; -extern uint32_t linker_RW_sections_size; -extern uint32_t linker_res_funcs_ZI_sections_size; -extern uint32_t linker_rel_dyn_GOT; - -/* Note that cmd_id is not used in a User Mode TA */ -const struct user_ta_func_head user_ta_func_head[] - __attribute__ ((section(".ta_func_head"))) = { - { 0, (uint32_t)ta_entry_open_session }, - { 0, (uint32_t)ta_entry_close_session }, - { 0, (uint32_t)ta_entry_invoke_command }, - { (TA_FLAG_USER_MODE | TA_FLAGS), 0 /* Spare */ }, - { (TA_DATA_SIZE), (TA_STACK_SIZE) }, -}; - -const struct user_ta_head ta_head __attribute__ ((section(".ta_head"))) = { +const struct ta_head ta_head __section(".ta_head") = { /* UUID, unique to each TA */ TA_UUID, - /* Number of functions in the TA */ - sizeof(user_ta_func_head) / sizeof(struct user_ta_func_head), - /* Section size information */ - (uint32_t)&linker_RO_sections_size, - (uint32_t)&linker_RW_sections_size, - (uint32_t)&linker_res_funcs_ZI_sections_size, - (uint32_t)&linker_rel_dyn_GOT, - /* Hash type, filled in by sign-tool */ - 0, - /* TA trace level */ - /* TA_TRACE_LEVEL_DEFAULT, */ + TA_STACK_SIZE, + TA_FLAG_USER_MODE | TA_FLAGS, + (uint32_t)ta_entry_open_session, + (uint32_t)ta_entry_close_session, + (uint32_t)ta_entry_invoke_command }; -/* Filled in by TEE Core when loading the TA */ -uint8_t *ta_heap_base __attribute__ ((section(".ta_heap_base"))); - -const size_t ta_data_size = TA_DATA_SIZE; +/* Keeping the heap in bss */ +uint8_t ta_heap[TA_DATA_SIZE]; +const size_t ta_heap_size = sizeof(ta_heap); const struct user_ta_property ta_props[] = { {TA_PROP_STR_SINGLE_INSTANCE, USER_TA_PROP_TYPE_BOOL, @@ -100,7 +100,12 @@ ta-srcfiles = ta/arch/$(ARCH)/user_ta_header.c \ $(foreach f, $(ta-srcfiles), \ $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/src))) +# Copy keys +ta-keys = keys/default_ta.pem +$(foreach f, $(ta-keys), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/keys))) + # Copy the scripts -ta-scripts = $(wildcard ta/arch/$(ARCH)/fix_ta_binary) +ta-scripts = $(wildcard scripts/sign.py) $(foreach f, $(ta-scripts), \ $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/scripts))) |