/*---------------------------------------------------------------------------*
  Project:  TwlSDK - ELF Loader
  File:     el.h

  Copyright 2006-2008 Nintendo. All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2008-12-10#$
  $Rev: 9620 $
  $Author: shirait $
 *---------------------------------------------------------------------------*/
#ifndef TWL_COMMON_EL_H_
#define TWL_COMMON_EL_H_

#ifdef SDK_TWL
#include <twl.h>
#else
#include <nitro.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif


/*------------------------------------------------------
  typedef
 -----------------------------------------------------*/
typedef u32   ELDlld;
typedef void *(*ELAlloc)(size_t size);
typedef void  (*ELFree)(void* ptr);
typedef u32   (*ELReadImage)( u32 offset, void* buf, u32 size);


/*------------------------------------------------------
  Constants specified with the EL_CalcEnoughBufferSizeforLink* functions
 -----------------------------------------------------*/
typedef enum ELLinkMode {
  EL_LINKMODE_ROUGH = 0,
  EL_LINKMODE_ONESHOT,
  EL_LINKMODE_RELATION
} ELLinkMode;

/*------------------------------------------------------
  Error Codes
 -----------------------------------------------------*/
#define EL_SUCCESS   0
#define EL_FAILED    1
#define EL_RELOCATED 0xF1    // For EL_ResolveAll only

/*------------------------------------------------------
  Detailed error codes obtained with EL_GetResultCode
 -----------------------------------------------------*/
typedef enum ELResult {
  EL_RESULT_SUCCESS = 0,
  EL_RESULT_FAILURE = 1,
  EL_RESULT_INVALID_PARAMETER,
  EL_RESULT_INVALID_ELF,
  EL_RESULT_UNSUPPORTED_ELF,
  EL_RESULT_CANNOT_ACCESS_ELF, //Error when opening or reading an ELF file
  EL_RESULT_NO_MORE_RESOURCE   //malloc failed
} ELResult;


/*------------------------------------------------------
  Address table for exporting
 -----------------------------------------------------*/
typedef struct {
  void*      next;              /*Next address entry*/
  char*      name;              /*String*/
  void*      adr;               /*Address*/
  u16        func_flag;         /*0: Data. 1: Function.*/
  u16        thumb_flag;        /*0: ARM code. 1: Thumb code.*/
}ELAdrEntry;


/*---------------------------------------------------------------------------*
  Name:         EL_Init

  Description:  Initializes the dynamic link system

  Arguments:    alloc: Function to get the heap
                free: Function to free the heap

  Returns:      0 on success and -1 on failure.
 *---------------------------------------------------------------------------*/
s32 EL_Init( ELAlloc alloc, ELFree free);


/*---------------------------------------------------------------------------*
  Name:         EL_CalcEnoughBufferSizeforLink*

  Description:  Tests a dynamic link and returns a buffer size sufficient to relocate it.
                Dynamic objects use external references, so a slightly large size will sometimes be returned.
                

  Arguments:    FilePath: The path name to the dynamic object
                buf: The buffer address to relocate to (nothing is actually written in it)
                readfunc: A read function prepared by the application
                len: The dynamic object size
                obj_image: The memory address where the dynamic object exists
                obj_len: The dynamic object size
                link_mode: Mode when testing a dynamic link
                            (this constant is used to make a trade-off between processing time and accuracy)

  Returns:      The buffer size on success and -1 on failure.
 *---------------------------------------------------------------------------*/
s32 EL_CalcEnoughBufferSizeforLinkFile( const char* FilePath, const void* buf, ELLinkMode link_mode);
s32 EL_CalcEnoughBufferSizeforLink( ELReadImage readfunc, u32 len, const void* buf, ELLinkMode link_mode);
s32 EL_CalcEnoughBufferSizeforLinkImage( void* obj_image, u32 obj_len, const void* buf, ELLinkMode link_mode);


/*---------------------------------------------------------------------------*
  Name:         EL_Link*

  Description:  Relocates a dynamic object (from a file, user function, or memory).

  Arguments:    FilePath: The path name to the dynamic object
                readfunc: A read function prepared by the application
                len: The dynamic object size
                obj_image: The memory address where the dynamic object exists
                obj_len: The dynamic object size
                buf: The buffer address to relocate to

  Returns:      A dynamic module handle on success and 0 on failure.
 *---------------------------------------------------------------------------*/
ELDlld EL_LinkFile( const char* FilePath, void* buf);
ELDlld EL_Link( ELReadImage readfunc, u32 len, void* buf);
ELDlld EL_LinkImage( void* obj_image, u32 obj_len, void* buf);


/*---------------------------------------------------------------------------*
  Name:         EL_ResolveAll

  Description:  Resolves unresolved symbols.

  Arguments:    None.

  Returns:      EL_RELOCATED on success and EL_FAILED on failure.
 *---------------------------------------------------------------------------*/
u16 EL_ResolveAll( void);


/*---------------------------------------------------------------------------*
  Name:         EL_Export

  Description:  Registers symbol information with the DLL system.

  Arguments:    None.

  Returns:      TRUE on success.
 *---------------------------------------------------------------------------*/
BOOL EL_Export( ELAdrEntry* AdrEnt);


/*---------------------------------------------------------------------------*
  Name:         EL_AddStaticSym

  Description:  Registers dynamic module symbol information with the DLL system.
                (This is defined as a weak symbol in the ELF library, and will be overwritten by the definition in files created by makelst)
                  
  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void EL_AddStaticSym( void);


/*---------------------------------------------------------------------------*
  Name:         EL_GetGlobalAdr

  Description:  Searches a dynamic module for a symbol and returns its address.

  Arguments:    my_dlld: The dynamic module handle to search
                ent_name: The symbol name

  Returns:      The symbol's address on success and 0 on failure.
 *---------------------------------------------------------------------------*/
void* EL_GetGlobalAdr( ELDlld my_dlld, const char* ent_name);


/*---------------------------------------------------------------------------*
  Name:         EL_Unlink

  Description:  Unlinks a dynamic module.

  Arguments:    my_dlld: The dynamic module handle to unlink

  Returns:      EL_SUCCESS on success and EL_FAILED on failure.
 *---------------------------------------------------------------------------*/
u16 EL_Unlink( ELDlld my_dlld);


/*---------------------------------------------------------------------------*
  Name:         EL_IsResolved

  Description:  Determines whether all of a dynamic module's external references have been resolved.

  Arguments:    my_dlld: The dynamic module handle to check

  Returns:      TRUE if there are still unresolved external references.
 *---------------------------------------------------------------------------*/
BOOL EL_IsResolved( ELDlld my_dlld);


/*---------------------------------------------------------------------------*
  Name:         EL_GetLibSize

  Description:  Returns the size of a linked dynamic module.
                The current size of the dynamic module will be returned, even if it still has unresolved external references.
                You can get the final size after relocation is complete by confirming in advance that EL_ResolveAll returns EL_RELOCATED.
                
                

  Arguments:    my_dlld: The dynamic module handle that will have its size checked

  Returns:      The size on success and 0 on failure.
 *---------------------------------------------------------------------------*/
u32 EL_GetLibSize( ELDlld my_dlld);


/*---------------------------------------------------------------------------*
  Name:         EL_GetResultCode

  Description:  Returns the detailed result of the last process to be run.

  Arguments:    None.

  Returns:      An ELResult error code.
 *---------------------------------------------------------------------------*/
ELResult EL_GetResultCode( void);


#ifdef __cplusplus
}    /* extern "C" */
#endif

#endif    /*TWL_COMMON_EL_H_*/
