/* This file defines standard ELF types, structures, and macros.
   Copyright (C) 1995-2003,2004,2005,2006,2007,2008,2009
	Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifndef _ELF_H_
#define	_ELF_H_ 1

#include <hal_types.h>

/*
 * Standard ELF types.
 */

#define EI_NIDENT (16)

/* 32bit version */
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef int32_t  Elf32_Sword;
typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;

/* 64bit version */
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef int32_t  Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;

/* ELF header - 32bit version. */
typedef struct
{
	unsigned char   e_ident[EI_NIDENT]; /* 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;

/* ELF header - 64bit version. */
typedef struct
{
	unsigned char   e_ident[EI_NIDENT]; /* 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 EI_* macros are indices into the
 * array. The macros under each EI_* macro are the values the byte
 * may have.
 */
#define EI_MAG0		0		/* File identification byte 0 index */
#define ELFMAG0		0x7f		/* Magic number byte 0 */

#define EI_MAG1		1		/* File identification byte 1 index */
#define ELFMAG1		'E'		/* Magic number byte 1 */

#define EI_MAG2		2		/* File identification byte 2 index */
#define ELFMAG2		'L'		/* Magic number byte 2 */

#define EI_MAG3		3		/* File identification byte 3 index */
#define ELFMAG3		'F'		/* Magic number byte 3 */

#define EI_CLASS	4		/* File class byte index */
#define ELFCLASSNONE	0		/* Invalid class */
#define ELFCLASS32	1		/* 32-bit objects */
#define ELFCLASS64	2	/* 64-bit objects */

#define ELFCLASSNUM	3

#define EI_DATA		5		/* Data encoding byte index */
#define ELFDATANONE	0		/* Invalid data encoding */
#define ELFDATA2LSB	1		/* 2's complement, little endian */
#define ELFDATA2MSB	2		/* 2's complement, big endian */
#define ELFDATANUM	3

#define EI_VERSION	6		/* File version byte index */
					/* Value must be EV_CURRENT */

#define EI_OSABI	7		/* OS ABI identification */
#define ELFOSABI_NONE		0	/* UNIX System V ABI */

/* Legal values for e_type (object file type).  */
#define ET_NONE		0		/* No file type */
#define ET_REL		1		/* Relocatable file */
#define ET_EXEC		2		/* Executable file */
#define ET_DYN		3		/* Shared object file */
#define ET_CORE		4		/* Core file */
#define	ET_NUM		5		/* Number of defined types */
#define ET_LOOS		0xfe00		/* OS-specific range start */
#define ET_HIOS		0xfeff		/* OS-specific range end */
#define ET_LOPROC	0xff00		/* Processor-specific range start */
#define ET_HIPROC	0xffff		/* Processor-specific range end */

/* Legal values for e_machine (architecture).  */
#define EM_NONE		 0		/* No machine */
#define EM_MIPS		 8		/* MIPS R3000 big-endian */
#define EM_MIPS_RS3_LE	10		/* MIPS R3000 little-endian */
#define EM_PPC		20		/* PowerPC */
#define EM_PPC64	21		/* PowerPC 64-bit */
#define EM_ARM		40		/* ARM */
#define EM_X86_64	62		/* AMD x86-64 architecture */

/* Legal values for e_version (version).  */
#define EV_NONE		0		/* Invalid ELF version */
#define EV_CURRENT	1		/* Current version */
#define EV_NUM		2

/* Program segment header - 32bit version. */
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;

/* Program segment header - 64bit version. */
typedef struct
{
	Elf64_Word  p_type;     /* Segment type */
	Elf64_Word  p_flags;    /* Segment flags */
	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;

/* Legal values for p_type (segment type).  */
#define	PT_NULL		0		/* Program header table entry unused */
#define PT_LOAD		1		/* Loadable program segment */
#define PT_DYNAMIC	2		/* Dynamic linking information */
#define PT_INTERP	3		/* Program interpreter */
#define PT_NOTE		4		/* Auxiliary information */
#define PT_SHLIB	5		/* Reserved */
#define PT_PHDR		6		/* Entry for header table itself */
#define PT_TLS		7		/* Thread-local storage segment */
#define	PT_NUM		8		/* Number of defined types */
#define PT_LOOS		0x60000000	/* Start of OS-specific */
#define PT_GNU_EH_FRAME	0x6474e550	/* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK	0x6474e551	/* Indicates stack executability */
#define PT_GNU_RELRO	0x6474e552	/* Read-only after relocation */
#define PT_LOSUNW	0x6ffffffa
#define PT_SUNWBSS	0x6ffffffa	/* Sun Specific segment */
#define PT_SUNWSTACK	0x6ffffffb	/* Stack segment */
#define PT_HISUNW	0x6fffffff
#define PT_HIOS		0x6fffffff	/* End of OS-specific */
#define PT_LOPROC	0x70000000	/* Start of processor-specific */
#define PT_HIPROC	0x7fffffff	/* End of processor-specific */

/* Legal values for p_flags (segment flags).  */
#define PF_X		(1 << 0)	/* Segment is executable */
#define PF_W		(1 << 1)	/* Segment is writable */
#define PF_R		(1 << 2)	/* Segment is readable */
#define PF_MASKOS	0x0ff00000	/* OS-specific */
#define PF_MASKPROC	0xf0000000	/* Processor-specific */

#if defined(HAL_32BIT)
#define Elf_Half  Elf32_Half
#define Elf_Word  Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Addr  Elf32_Addr
#define Elf_Off   Elf32_Off
#define Elf_Ehdr  Elf32_Ehdr
#define Elf_Phdr  Elf32_Phdr
#define ELFCLASS  ELFCLASS32
#elif defined (HAL_64BIT)
#define Elf_Half  Elf64_Half
#define Elf_Word  Elf64_Word
#define Elf_Sword Elf64_Sword
#define Elf_Xword Elf64_Xword
#define Elf_Addr  Elf64_Addr
#define Elf_Off   Elf64_Off
#define Elf_Ehdr  Elf64_Ehdr
#define Elf_Phdr  Elf64_Phdr
#define ELFCLASS  ELFCLASS64
#else
#error "Must define HAL_64BIT/HAL_32BIT"
#endif

/****************************************************************************************
 * This function registers in VMM the CODE and DATA vsegs defined in the .elf file.
 * The segments are not loaded in memory.
 * It also registers the process entry point in VMM.
 ****************************************************************************************
 * @ pathname : local pointer on .elf file pathname (in kernel space).
 * @ process  : local pointer on target process descriptor.
 ***************************************************************************************/
error_t elf_load_process( char      * pathname,
                          process_t * process);

#endif	/* elf.h */
