/****************************************************************************
**
**  Name:  LDATA.C
**
**  Description:
**      Process data part of ELF binary file.
**
**  $Log:   S:/tbird/arcppc/lelf/ldata.c_v  $
** 
**    Rev 1.6   31 Mar 1997 08:45:36   hera
** 
**    Rev 1.5   24 Mar 1997 13:57:36   hera
**
**  $Header:   S:/tbird/arcppc/lelf/ldata.c_v   1.6   31 Mar 1997 08:45:36   hera  $
**
**  Copyright (C) 1991-1993 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _SDPROBE_
#include "sdprobe.h"
#endif

#ifndef _SSHARED_
#include "sshared.h"
#endif

#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif

#ifndef __ERR__
#include "err.h"
#endif

#ifndef __LDR__
#include "ldr.h"
#endif

#ifndef _LQUEUE_
#include "lqueue.h"
#endif

#ifndef _LFLAGS_
#include "lflags.h"
#endif

#ifndef _CLIULIB_
#include "cliulib.h"
#endif

#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef __LSYM__
#include "lsym.h"
#endif

#include <io.h>

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern Elf32_Endr HdrELF;
extern Elf32_Phdr *execution_info[10];

extern LDRSTATBLOCK FAR *lstb; /* progress reporting status block */
extern U16 indexBufferError;   /* index of first buffer recording error */
extern U32 ldrFlags;   /* loader options */

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE PRIVATE ProcessDataAction(HANDLE hfile, U32 *bytesLoaded);
RETCODE EXPORT ReadBytes(VOID *info, U8 *dest, U32 count);
RETCODE PRIVATE LdrProcessVerifyError(VOID);

                       /****************************
                        *                          *
                        *     EXECUTABLE CODE      *
                        *                          *
                        ****************************/

/****************************************************************************
**
**  ProcessDataPart
**
**  This function is called from ldr.c after the section info has
**  been obtained from Section Part of file.
**   
**  This function picks out LD (load constant byte) and RE (repeat)
**  records from the data section of the file and writes them to
**  memory.  ASP records indicate a change in address; otherwise
**  successive LD and RE records are contiguous in memory.
**
**  Note that this code supports LD and RE records of arbitrary size.
**  ELF specifies a maximum of 128 bytes in LD and RE records.
**  This support is needed since some compilers are not quite IEEE-compliant.
**
*****************************************************************************/
RETCODE ProcessDataPart(HANDLE hfile, U32 *bytesLoaded) {
   RETCODE err,err2;  


   if ((err = LdrQueueInit()) != GOOD) return(err);
   err = ProcessDataAction(hfile, bytesLoaded);
   err2 = LdrQueueWait();

   // NOTES: Nghia - 10/28/93
   // Handle Loading verify error - retrieve the information to report  
   if ((err = (err ? err: err2)) == ER_MEMORY_VERIFY)
      LdrProcessVerifyError();
   return(err);
}

/***************************************************************************
**
**  ProcessDataAction
**
*****************************************************************************/
RETCODE PRIVATE ProcessDataAction(HANDLE hfile, U32 *bytesLoaded) {
   RETCODE err;
   BOOLEAN aborted;
   U32 Paddr, addrBitsChanged;
   U16 index;  
   U32 currentLoadAddr,byteCount;
   U32 appendSize;
   currentLoadAddr = 0ul;
   *bytesLoaded = 0ul;
  
   /*
   ** Seek to data part of file
   */

   for(index = 0; index < HdrELF.e_phnum; index++)
   {
    if (SeekELFFile(hfile, execution_info[index]->p_offset, SEEK_SET) == -1L)
      return (ER_BAD_SEEK);

      Paddr = execution_info[index]->p_vaddr;
      /* Send new address record, changing as few bytes as possible */
      if ((addrBitsChanged = Paddr ^ currentLoadAddr) != 0) {
         if ((err = LdrQueueSetAddressRecord(Paddr,
            BYTES_TO_TRANSMIT(addrBitsChanged))) != GOOD) return(err);
         currentLoadAddr = Paddr;
      }  
      if ((err = LdrQueueCheckLoadAbort()) != GOOD) return(err);
      if ((err = LdrQueueGetLoadAbort(&aborted)) != GOOD) return(err);
      if (aborted) return(ER_USER_ABORT);

      byteCount = execution_info[index]->p_filesz;
      while (byteCount >= LDR_BUFSIZE){
	 U32 Offset;
         Offset = tell(hfile);
	 if ((err = LdrQueueDataRecord(&hfile, ReadBytes,
            currentLoadAddr, LDR_BUFSIZE, 0)) != GOOD) return(err); /*Load 4096 Bytes*/
         byteCount = byteCount - LDR_BUFSIZE;
	 currentLoadAddr += LDR_BUFSIZE;
	 if (lstb != NULL) {
	    lstb->numBytes += LDR_BUFSIZE;
            lstb->curLocation = tell(hfile);
         }
	 if (LdrProgressInc() == ER_LDR_ABORT) return(ER_LDR_ABORT);
      }
      if(byteCount > 0){
         if((err = LdrQueueDataRecord(&hfile, ReadBytes,
	    currentLoadAddr,byteCount,0)) != GOOD)
	    return(err);	 
	 currentLoadAddr += byteCount;
	 if (lstb != NULL) {
            lstb->numBytes += byteCount;
            lstb->curLocation = tell(hfile);
         }
	 if(LdrProgressInc() == ER_LDR_ABORT) return(ER_LDR_ABORT);
	 byteCount = 0;
      }
      //*if memory size > file size, append 0 to memory*/
      appendSize = execution_info[index]->p_memsz - execution_info[index]->p_filesz;
      while(appendSize >= LDR_BUFSIZE){
         if ((err = LdrQueueDataRecord(&hfile, ReadBytes,
            currentLoadAddr,0,LDR_BUFSIZE)) != GOOD) return(err);
	 currentLoadAddr += LDR_BUFSIZE;
	 appendSize -= LDR_BUFSIZE;
	 if (lstb != NULL)
	    lstb->numBytes += LDR_BUFSIZE;
	 if (LdrProgressInc() == ER_LDR_ABORT) return (ER_LDR_ABORT);
      }
      if(appendSize > 0){
         if((err = LdrQueueDataRecord(&hfile, ReadBytes,
	    currentLoadAddr,0,appendSize)) != GOOD)
	    return(err);	 
	 currentLoadAddr += appendSize;
	 if (lstb != NULL)
            lstb->numBytes += appendSize;
	 if (LdrProgressInc() == ER_LDR_ABORT) return (ER_LDR_ABORT);
	 appendSize = 0;
      }
      *bytesLoaded += execution_info[index]->p_memsz;
   }
   /* send partially filled load buffer to box */
   return(LdrQueueFlush(currentLoadAddr));
}

/***************************************************************************
**
**  LdrProcessVerifyError
**
*****************************************************************************/
RETCODE PRIVATE LdrProcessVerifyError(VOID) {
//   U32 verifyOffset;
//   U32 expectedData, actualData;
//   U16 addrSpace;
   S8 verBuf[ADDR_BUFF_SZ], spaceBuf[4];
   DESCRIPTOR addr;
   CHAR verifyErrorString[E_ERRSIZE];
   RETCODE err;
   BAD_MEMORY verifyErrorInfo;

   /* Make sure that we are not going to crash */
   if (indexBufferError >= NUM_LOAD) 
      return(GOOD);
      
   /* collect information of the indexBufferError */
//   SdnReadMember(SDN_LVERIFY_OFFSET+indexBufferError, (U8 *)&verifyOffset);
//   SdnReadMember(SDN_LVERIFY_EXPECTED+indexBufferError ,(U8 *)&expectedData);
//   SdnReadMember(SDN_LVERIFY_ACTUAL+indexBufferError, (U8 *)&actualData);
//   SdnReadMember(SDN_LVERIFY_SPACE+indexBufferError, (U8 *)&addrSpace);

   iceGetVerifyErrorInfo(&verifyErrorInfo);
   
   if ((err = AdrCreateAddress(&addr)) != GOOD)
      return(err);
   AdrSetAddrOffset(addr, verifyErrorInfo.offset);
   AdrConvAddressToTextWithParams(addr, TRUE, TRUE, verBuf);
   AdrDestroyAddress(addr);

   /* format message */
   wsprintf(spaceBuf," ");
   /****
   switch (verifyErrorInfo.space) {
      case SPACE_UNDEF0:
         wsprintf(spaceBuf,"U0 ");
      break;
      case SPACE_UD:
         wsprintf(spaceBuf,"UD ");
      break;
      case SPACE_UP:
         wsprintf(spaceBuf,"UP ");
      break;
      case SPACE_UNDEF3:
         wsprintf(spaceBuf,"U3 ");
      break;
      case SPACE_UNDEF4:
         wsprintf(spaceBuf,"U4 ");
      break;
      case SPACE_SD:
         wsprintf(spaceBuf,"SD ");
      break;
      case SPACE_SP:
         wsprintf(spaceBuf,"SP ");
      break;
      case SPACE_CPU:
         wsprintf(spaceBuf,"CPU");
      break;
      case SPACE_DONT_CARE:
         wsprintf(spaceBuf,"   ");
      break;
   }
   ****/
   wsprintf(verifyErrorString,
      "address: %s %s, expected: 0x%04X, actual: 0x%04X",
       verBuf, spaceBuf, (U16)verifyErrorInfo.expected,
       (U16)verifyErrorInfo.actual);

   /* send error text in error text server */
   return(ErrSaveMemoryVerifyInfo((LPSTR)verifyErrorString));
}

/***************************************************************************
**
**  ReadBytes
**
*****************************************************************************/
RETCODE EXPORT ReadBytes(VOID *info, U8 *dest, U32 count) {
   return(GetELFBytes(*((HANDLE*)info), dest, count));
}
/******************************** E O F ***********************************/
