/*
 * Copyright (c) 2018-2020, 2023 Qualcomm Technologies, Inc.
 * All Rights Reserved.
 * Confidential and Proprietary - Qualcomm Technologies, Inc.
 */

// TODO: [added by amavrin, FR 76706] This workaround needs to be fixed - i.e., moved out from the public header to
//  the component that is using it (looks like it is ssg/securemsm/trustzone/qsee/mink/app_mgr/posix_port/...).
//  This was not noticed before as the "elflib" was not part of the off-target. Now, it is required as a dependency
//  for the "secimgauth". Please clean up ssg/securemsm/trustzone/qsee/mink/elflib/build/SConscript after the fix.
#if defined(ELF_HEADER)
/*
 * Defined as either local elf.h, /pkg/ssg/toolchain's elf.h, or Android NDK toolchain's elf.h,
 * depending on build options.
 *
 * Unfortunately mink/elflib/inc comes first in the include path list so this file will always be
 * included first.
 */
#include ELF_HEADER
#else

#ifndef __ELF_H
#define __ELF_H

#include <stdint.h>

#define ELFINFO_MAGIC_SIZE (16U)

/*
 * These types are defined in the following documentation:
 *
 *   http://infocenter.arm.com/help/topic/com.arm.doc.espc0003/ARMELF.pdf
 *   https://uclibc.org/docs/elf-64-gen.pdf
 *
 * We specifically use these types to make it easier to
 * compare the documentation against the source.
 */

typedef uint16_t  Elf32_Half;
typedef uint16_t  Elf64_Half;

typedef uint32_t  Elf32_Word;
typedef int32_t   Elf32_Sword;
typedef uint32_t  Elf64_Word;
typedef int32_t   Elf64_Sword;

typedef uint64_t  Elf32_Xword;
typedef int64_t   Elf32_Sxword;
typedef uint64_t  Elf64_Xword;
typedef int64_t   Elf64_Sxword;

typedef uint32_t  Elf32_Addr;
typedef uint64_t  Elf64_Addr;

typedef uint32_t  Elf32_Off;
typedef uint64_t  Elf64_Off;

typedef struct {
  uint8_t         e_ident[ELFINFO_MAGIC_SIZE]; /** Magic number and other info   */
  Elf32_Half      e_type;               /** Object file type                    */
  Elf32_Half      e_machine;            /** Architecture                        */
  Elf32_Word      e_version;            /** Object file version                 */
  Elf32_Addr      e_entry;              /** Entry point virtual address         */
  Elf32_Off       e_phoff;              /** Program header table file offset    */
  Elf32_Off       e_shoff;              /** Section header table file offset    */
  Elf32_Word      e_flags;              /** Processor-specific flags            */
  Elf32_Half      e_ehsize;             /** ELF header size in bytes            */
  Elf32_Half      e_phentsize;          /** Program header table entry size     */
  Elf32_Half      e_phnum;              /** Program header table entry count    */
  Elf32_Half      e_shentsize;          /** Section header table entry size     */
  Elf32_Half      e_shnum;              /** Section header table entry count    */
  Elf32_Half      e_shstrndx;           /** Section header string table index   */
} Elf32_Ehdr;

typedef struct {
  uint8_t         e_ident[ELFINFO_MAGIC_SIZE]; /** Magic number and other info   */
  Elf64_Half      e_type;               /** Object file type                    */
  Elf64_Half      e_machine;            /** Architecture                        */
  Elf64_Word      e_version;            /** Object file version                 */
  Elf64_Addr      e_entry;              /** Entry point virtual address         */
  Elf64_Off       e_phoff;              /** Program header table file offset    */
  Elf64_Off       e_shoff;              /** Section header table file offset    */
  Elf64_Word      e_flags;              /** Processor-specific flags            */
  Elf64_Half      e_ehsize;             /** ELF header size in bytes            */
  Elf64_Half      e_phentsize;          /** Program header table entry size     */
  Elf64_Half      e_phnum;              /** Program header table entry count    */
  Elf64_Half      e_shentsize;          /** Section header table entry size     */
  Elf64_Half      e_shnum;              /** Section header table entry count    */
  Elf64_Half      e_shstrndx;           /** Section header string table index   */
} Elf64_Ehdr;

/* Fields in the e_ident array.  The ELFINFO_*_INDEX macros are
 * indices into the array.  The macros under each ELFINFO_* macro
 * is the values the byte may have.
 */

#define ELFINFO_MAG0_INDEX    0U     /* File identification byte 0 index */
#define ELFINFO_MAG0          0x7fU  /* Magic number byte 0              */

#define ELFINFO_MAG1_INDEX    1U     /* File identification byte 1 index */
#define ELFINFO_MAG1         'E'     /* Magic number byte 1              */

#define ELFINFO_MAG2_INDEX    2U     /* File identification byte 2 index */
#define ELFINFO_MAG2         'L'     /* Magic number byte 2              */

#define ELFINFO_MAG3_INDEX    3U     /* File identification byte 3 index */
#define ELFINFO_MAG3         'F'     /* Magic number byte 3              */

#define ELFINFO_CLASS_INDEX   4U     /* File class byte index            */

/* ELF Object Type */
#define ELF_CLASS_32          1U     /* 32-bit objects                   */
#define ELF_CLASS_64          2U     /* 64-bit objects                   */

/* Version information */
#define ELFINFO_VERSION_INDEX 6U     /* File version byte index          */
#define ELF_VERSION_CURRENT   1U     /* Current version                  */

#define EM_ARM                40U    /* Ehdr.e_machine                   */
#define EM_DSP6               164U   /* Qualcomm DSP6                    */
#define EM_AARCH64            183U   /* ARM AArch64                      */
#define ET_NONE               0U
#define ET_REL                1U
#define ET_EXEC               2U
#define ET_DYN                3U

typedef struct {
  Elf32_Word      p_type;               /** Segment type */
  Elf32_Off       p_offset;             /** Segment file offset */
  Elf32_Addr      p_vaddr;              /** Segment virtual address */
  Elf32_Addr      p_paddr;              /** Segment physical address */
  Elf32_Word      p_filesz;             /** Segment size in file */
  Elf32_Word      p_memsz;              /** Segment size in memory */
  Elf32_Word      p_flags;              /** Segment flags */
  Elf32_Word      p_align;              /** Segment alignment */
} Elf32_Phdr;

typedef struct
{
  Elf64_Word      p_type;               /** Segment type */
  Elf64_Word      p_flags;              /** Segment attributes */
  Elf64_Off       p_offset;             /** Segment file offset */
  Elf64_Addr      p_vaddr;              /** Segment virtual address */
  Elf64_Addr      p_paddr;              /** Segment physical address */
  Elf64_Xword     p_filesz;             /** Segment size in file */
  Elf64_Xword     p_memsz;              /** Segment size in memory */
  Elf64_Xword     p_align;              /** Segment alignment */
} Elf64_Phdr;

typedef struct {
  Elf32_Addr      r_offset;             /** Address of reference */
  Elf32_Word      r_info;               /** Relocation type and symbol index */
} Elf32_Rel;

typedef struct {
  Elf64_Addr      r_offset;             /** Address of reference */
  Elf64_Xword     r_info;               /** Relocation type and symbol index */
} Elf64_Rel;

typedef struct {
  Elf32_Addr      r_offset;             /** Address of reference */
  Elf32_Word      r_info;               /** Relocation type and symbol index */
  Elf32_Sword     r_addend;             /** Addend */
} Elf32_Rela;

typedef struct {
  Elf64_Addr      r_offset;             /** Address of reference */
  Elf64_Xword     r_info;               /** Relocation type and symbol index */
  Elf64_Sxword    r_addend;             /** Addend */
} Elf64_Rela;

typedef struct {
  Elf32_Word      st_name;              /* Symbol name (string tbl index) */
  Elf32_Addr      st_value;             /* Symbol value */
  Elf32_Word      st_size;              /* Symbol size */
  uint8_t         st_info;              /* Symbol type and binding */
  uint8_t         st_other;             /* Symbol visibility */
  Elf32_Half      st_shndx;             /* Section index */
} Elf32_Sym;

typedef struct {
  Elf64_Word      st_name;              /* Symbol name (string tbl index) */
  uint8_t         st_info;              /* Symbol type and binding */
  uint8_t         st_other;             /* Symbol visibility */
  Elf64_Half      st_shndx;             /* Section index */
  Elf64_Addr      st_value;             /* Symbol value */
  Elf64_Xword     st_size;              /* Symbol size */
} Elf64_Sym;

typedef struct {
  Elf32_Sword     d_tag;                /* Dynamic entry type */
  union {
    Elf32_Word      d_val;              /* Integer value */
    Elf32_Addr      d_ptr;              /* Address value */
  } d_un;
} Elf32_Dyn;

typedef struct {
  Elf64_Sxword    d_tag;                /* Dynamic entry type */
  union {
    Elf64_Xword     d_val;              /* Integer value */
    Elf64_Addr      d_ptr;              /* Address value */
  } d_un;
} Elf64_Dyn;

#define DT_NULL         0U
#define DT_NEEDED       1U
#define DT_PLTRELSZ     2U
#define DT_PLTGOT       3U
#define DT_HASH         4U
#define DT_STRTAB       5U
#define DT_SYMTAB       6U
#define DT_RELA         7U
#define DT_RELASZ       8U
#define DT_RELAENT      9U
#define DT_STRSZ        10U
#define DT_SYMENT       11U
#define DT_INIT         12U
#define DT_FINI         13U
#define DT_SONAME       14U
#define DT_RPATH        15U
#define DT_SYMBOLIC     16U
#define DT_REL          17U
#define DT_RELSZ        18U
#define DT_RELENT       19U
#define DT_PLTREL       20U
#define DT_DEBUG        21U
#define DT_TEXTREL      22U
#define DT_JMPREL       23U
#define DT_BIND_NOW     24U
#define DT_INIT_ARRAY   25U
#define DT_FINI_ARRAY   26U
#define DT_INIT_ARRAYSZ 27U
#define DT_FINI_ARRAYSZ 28U
#define DT_RUNPATH      29U
#define DT_FLAGS        30U
#define DT_ENCODING     32U
#define DT_PREINIT_ARRAY 32U
#define DT_PREINIT_ARRAYSZ 33U
#define DT_NUM          34U

#define R_ARM_NONE              0U
#define R_ARM_PC24              1U
#define R_ARM_ABS32             2U
#define R_ARM_REL32             3U
#define R_ARM_PC13              4U
#define R_ARM_ABS16             5U
#define R_ARM_ABS12             6U
#define R_ARM_THM_ABS5          7U
#define R_ARM_ABS8              8U
#define R_ARM_SBREL32           9U
#define R_ARM_THM_PC22          10U
#define R_ARM_THM_PC8           11U
#define R_ARM_AMP_VCALL9        12U
#define R_ARM_TLS_DESC          13U
#define R_ARM_THM_SWI8          14U
#define R_ARM_XPC25             15U
#define R_ARM_THM_XPC22         16U
#define R_ARM_TLS_DTPMOD32      17U
#define R_ARM_TLS_DTPOFF32      18U
#define R_ARM_TLS_TPOFF32       19U
#define R_ARM_COPY              20U
#define R_ARM_GLOB_DAT          21U
#define R_ARM_JUMP_SLOT         22U
#define R_ARM_RELATIVE          23U

#define R_AARCH64_NONE          0U    /* No relocation. */
#define R_AARCH64_ABS64         257U  /* Direct 64 bit. */
#define R_AARCH64_ABS32         258U  /* Direct 32 bit. */
#define R_AARCH64_ABS16         259U  /* Direct 16-bit. */
#define R_AARCH64_PREL64        260U  /* PC-relative 64-bit. */
#define R_AARCH64_PREL32        261U  /* PC-relative 32-bit. */
#define R_AARCH64_PREL16        262U  /* PC-relative 16-bit. */
#define R_AARCH64_COPY          1024U /* Copy symbol at runtime. */
#define R_AARCH64_GLOB_DAT      1025U /* Create GOT entry. */
#define R_AARCH64_JUMP_SLOT     1026U /* Create PLT entry. */
#define R_AARCH64_RELATIVE      1027U /* Adjust by program base. */
#define R_AARCH64_TLS_DTPMOD64  1028U /* Module number, 64 bit. */
#define R_AARCH64_TLS_DTPREL64  1029U /* Module-relative offset, 64 bit. */
#define R_AARCH64_TLS_TPREL64   1030U /* TP-relative offset, 64 bit. */
#define R_AARCH64_TLSDESC       1031U /* TLS Descriptor. */
#define R_AARCH64_IRELATIVE     1032U /* Indirect(Delta(S)+ A) */

#define PT_NULL      0U         /** NULL Segment */
#define PT_LOAD      1U         /** Load Segment */
#define PT_DYNAMIC   2U         /** Dynamic Segment */
#define PT_GNU_RELRO 0x6474e552U /** RELRO Segment */

#define PT_FLAG_HASH_TYPE_MASK     0x2000000U
#define PT_FLAG_MANIFEST_TYPE_MASK 0x4000000U
#define PT_FLAG_TYPE_MASK          0x7000000U

/* Fields in the e_ident array.  The ELFINFO_*_INDEX macros are
 * indices into the array.
 */
#define ELFINFO_CLASS_INDEX   4U     /* File class byte index            */

/* Special section indices */
#define SHN_UNDEF 0U
#define SHN_ABS   0xfff1

/* End of a chain in the hash table  */
#define STN_UNDEF 0U

/* Special symbol table index. */
#define ELF_ST_BIND(i)   ((i)>>4)
#define ELF_ST_TYPE(i)   ((i) & 0xFU)
#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xfU))

#define STB_LOCAL    0U
#define STB_GLOBAL   1U
#define STB_WEAK     2U
#define STB_LOPROC  13U
#define STB_HIPROC  15U

#define STT_NOTYPE   0U
#define STT_OBJECT   1U
#define STT_FUNC     2U
#define STT_SECTION  3U
#define STT_FILE     4U
#define STT_LOPROC  13U
#define STT_HIPROC  15U

#define ELF32_R_SYM(i)      ((i) >> 8)
#define ELF32_R_TYPE(i)     ((i) & 0xffU)
#define ELF32_R_INFO(s, t)  (((s) << 8) + ((t) & 0xffU))

#define ELF64_R_SYM(i)      ((i) >> 32)
#define ELF64_R_TYPE(i)     ((i) & 0xffffffffU)
#define ELF64_R_INFO(s,t)   ((((uint64_t) (s)) << 32) + (t))

#endif  /* __ELF_H */
#endif  /* NOT ELF_HEADER */
