/****************************************************************************
**
**  Name:  SREC.C
**
**  Description:
**      Entry points for the Srecord loader.
**      Primary API's live here.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/arcppc/loader/srec/srec.c_v  $
** 
**    Rev 1.0   13 Jan 1998 14:00:32   hera
** Initial revision.
** 
**    Rev 1.0   13 Jan 1998 13:34:14   hera
** Initial revision.
** 
**    Rev 1.0   30 Sep 1997 16:03:28   gene
** Initial revision.
** 
**    Rev 1.15   30 Aug 1993 11:13:24   ron
** Changes for Load Progress dialog
** 
**    Rev 1.14   28 Jul 1993 11:06:46   courtney
** Macros REPORT_* now correctly set boolean value for loader state
** variables; SymRemoveSymbols *always* will get called before each
** load, since SymAddLoadStart fails to recognize symbols have already
** been loaded for Srecord loadfiles (bug); FreeSections called once
** only in normal load case (not tied to symbol loading).
** 
**    Rev 1.13   26 Jul 1993 09:39:50   ernie
** Fixed error code returned to shell when symbols already loaded.
** 
**    Rev 1.12   26 Jul 1993 08:50:38   ernie
** Removed EVENT_MEM_EDIT.  This is now propagated by EVENT_LDR_MEMCHANGED.
** 
**    Rev 1.11   13 Jul 1993 09:42:44   ernie
** 1. Removed call to InitHexTable--this is now statically initialized.
** 2. Removed calls to register codebufs--these are no longer used.
** 3. Added event EVENT_LDR_MEMCHANGED to inform the memory server that
**    the loader has modified memory and that its caches should be flushed.
** 4. Added event EVENT_MEM_EDIT to inform presenters that memory was changed.
**    Normally EVENT_LDR_LOADCOMPLETE does this, but this event was removed
**    for other reasons.
** 
**    Rev 1.10   04 Jun 1993 10:30:44   nghia
** Revised to meet coding standard.
** Reported error using only the Warning() and WarningEx() routines.
** Removed dead code. - PIP for Source.
** 
**    Rev 1.9   12 Feb 1993 18:04:52   nghia
** Removed all #if ? and #endif.
** Fixed bug caused memory leakage.
** Fixed bug caused file handle not being closed when user abort or error.
** Updated for release.
** 
**    Rev 1.8   03 Dec 1992 17:45:34   courtney
** Added comment to InitCServer.
** 
**    Rev 1.7   06 Nov 1992 17:34:40   courtney
** Update local nSections after freeing.
** 
**    Rev 1.6   04 Nov 1992 17:40:12   courtney
** Add runMode parameter to entry point (inherits from 695 loader).
** 
**    Rev 1.5   22 Oct 1992 17:18:46   courtney
** Revise parameters to ProcessSymbols to pass symload flag.
** 
**    Rev 1.4   22 Oct 1992 16:13:16   courtney
** Cleanup error reporting to use generic loader's string resource messages.
** 
**    Rev 1.3   25 Sep 1992 21:07:10   courtney
** Added symbol support.
** 
**    Rev 1.2   25 Sep 1992 05:44:08   courtney
** Add PRIVATEs (?not used); add info msg calls; update code; add
** cleanup routine; *no* events.
** 
**    Rev 1.1   21 Aug 1992 10:24:34   courtney
** Update return codes, update (unused) InitCServer to new style.
** 
**    Rev 1.0   31 Dec 1991 09:33:54   courtney
** Initial revision.
** 
**  $Header:   S:/tbird/arcppc/loader/srec/srec.c_v   1.0   13 Jan 1998 14:00:32   hera  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#ifndef _CLISRV_
#include "clisrv.h"
#endif
#ifndef _ENLIB_
#include "enlib.h"
#endif
#ifndef _EVENTS_
#include "events.h"
#endif
#ifndef _HEAP_
#include "heap.h"
#endif
#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef _SLDR_
#include "sldr.h"
#endif

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

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

#ifdef SREC_PERF
#include <time.h>
#endif

#include <io.h>
#include <fcntl.h>

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

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
/* Note:  all data global to this DLL will either be recycled/reset on
   a new load invocation, or destroyed/deallocated at the end of this load.
*/
CHAR errbuf[80];

/* Global to srec (inherited from 695 loader) */
BOOL runMode = INTERACTIVE;  /* batch vs. interactive */
HANDLE cliServerHandle;
HANDLE dllServerHandle;
U16 reportWarning = TRUE;  /* warnings on by default */
U16 reportOn = TRUE;  /* report status by default */

/*
** PRIVATE data, needs to be retained for event callbacks on code/sym
** load complete
*/
/* the following are for options callback - Source Presenter */
S8 lpLoadfile[PATHLEN];
U16 ldrFlags;
LDRSTATBLOCK FAR *lstb; /* loader status block */

extern nSections;
extern enum INFOMSG infotype;
extern S16 numBytesInBuff;
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern CHAR *infomsg[];

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/

PRIVATE VOID Cleanup(U16);
                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/*
** This is the only entry point (called by the 695 loader)
*/
/*****************************************************************************
**
**  SldLoadWin
**
*****************************************************************************/
RETCODE EXPORT SldLoadWin(LPSTR lpBinfile, U16 flags, BOOL runModeFlag,
   LDRSTATBLOCK FAR *lplstb) {
   /* lpBinfile - load filename (.ABS srecord file)
      flags - code/symbols/status (see sldrsvr.h #defines)
   */
   FILE *fpBinfile;      // File Handle
   CHAR pfile[PATHLEN];  /* near buffer */
   RETCODE err;
   U32 nLoaded=0L;
   TIMESTAMP_TYPE mtime_disk;
   RETCODE symerr;
   U16 status;

#ifdef SREC_PERF
    // To measure loader download performance
    time_t first, second;
    first = time(NULL);
#endif

    lstb = lplstb; /* save status block pointer */
    /* set up statics for callback from Source Presenter */
    lstrcpy((LPSTR)lpLoadfile, (LPSTR)lpBinfile);
    ldrFlags = flags;
    /* check status option */
    reportOn = REPORT_STATUS(flags) ? TRUE : FALSE;
    reportWarning = REPORT_WARNING(flags) ? TRUE : FALSE;
    runMode = runModeFlag;

	/* This is the main entry point for the Loader. */
    /* copy filename to near buffer so we can use fopen */
    lstrcpy((LPSTR)pfile, lpBinfile);
    // Open loadfile
    if ((fpBinfile = fopen(pfile, "r")) == NULL) {
       err = LERR_CANNOT_OPEN;
       return (err);
	}
    // Reset counter of fileBuff
    numBytesInBuff = 0;
    GetTimestamp(fileno(fpBinfile), &mtime_disk);

   /*
   ** Even if not loading symbols, need to process symbols if only to
   ** skip over them
   */
   if (LOAD_SYM(flags)) {
      /* The symbol table fails to return SYM ALREADY error for Srecord
         loads, so we always clear out the symbol table first.
      */
      SymRemoveSymbols();
      symerr = SymAddLoadStart((LPSTR)pfile, INITIAL_LOAD, &mtime_disk);
      /* Check for SYM_ALREADY, query , etc. popup.  Though this currently
         does not work for Srecord loads, that is a BUG and should be fixed.
         Hence this code remains.
      */
      if (symerr == ER_SYMBOLS_LOADED) {
         err = LERR_SYM_ALREADY;
         /* Only query if user is capable of response (project presenter
         ** invocation).  If reload option is set from cli invocation, we
         ** just do it.  Else we return error.
         */
         switch (runMode) {
            case BATCH:
               if (RELOAD(flags) || !REPORT_WARNING(flags))
                  status = QOK;
               else {
                  fclose(fpBinfile);
                  return (ER_SYM_ALREADY_CLI);
               }
               break;
            case INTERACTIVE:
               if (REPORT_WARNING(flags))
                  status = Query(err);
               else
                  status = QOK;
               break;
         }
         if (status == QOK) {
            /* unload symbols from ST */
            SymRemoveSymbols();
            /* clear static data from Ldr - try again */
            symerr = SymAddLoadStart((LPSTR)pfile, INITIAL_LOAD, &mtime_disk);
            if (symerr == ER_SYMBOLS_LOADED) {
               /* give up, symbol table refuses to clear */
               fclose(fpBinfile);
               return (err);
            }
         } else if (status == QCANCEL) {
            fclose(fpBinfile);
            return (err);
         } else {
            /* unrecognized error probably from CLI */
            fclose(fpBinfile);
            return (err);
         }
      } /* End of symErr */
      /* Need to overwrite standard int types:
      ** Need to verify processor with proc.dll - these values reflect
      ** 68K family
      */
      SymAddTypeOverwriteSize((U8)T695_INT, (U8)SZ_STACKPUSH_68K);
      SymAddTypeOverwriteSize((U8)T695_UNS, (U8)SZ_STACKPUSH_68K);
      SymAddTypeOverwriteSize((U8)T695_UNS_INT, (U8)SZ_STACKPUSH_68K);
   }  /* LOAD_SYM */

   /* Process even if nosym/nocode - It allocate memory */
   ProcessSecPart(LOAD_SYM(flags));
   if ((err = ProcessSymbols(fpBinfile, &nLoaded, LOAD_SYM(flags))) != GOOD) {
      /* check for user abort (within routine) */
      fclose(fpBinfile);
      FreeSections((U16 *) &nSections);
      return(err);  /* exit */
   }

   if (LOAD_SYM(flags)) {
      if ((symerr = SymAddLoadEnd()) != GOOD)
         Warning(symerr);
   }

   /* check for user abort */
   if (CHECK_ABORT()) {
      fclose(fpBinfile);
      Cleanup(flags);
      return(LERR_LDR_ABORT);
   }
   if (LOAD_CODE(flags)) {
      nLoaded = 0L;
      /* should now be positioned to process srecords */
      /* process and load code and constant data records */
      if ((err = ProcessDataPart(fpBinfile, &nLoaded)) != GOOD) {
         fclose(fpBinfile);
         Cleanup(flags);
         return(err);  /* exit */
      }
#ifdef SREC_PERF
      second = time(NULL);
      wsprintf(errbuf, "Load %ld bytes in %ld seconds", nLoaded,
         second-first);
      InfoMsg(errbuf, IM_DISPLAY);
#endif
      infotype = LD_CODE_LOADED;
      wsprintf(errbuf, "%ld %s", nLoaded, (LPSTR)infomsg[infotype]);
      InfoMsg(errbuf, IM_COLLECT);

      EnlEventNotify(EVENT_LDR_MEMCHANGED);

   // NOTES: !!!
   // Is this info available in srec file??
   //     EnlEventNotify(EVENT_LDR_STARTPC);
   //     EnlEventNotify(EVENT_LDR_STACKTOP);
   //
   }
   fclose(fpBinfile);
   FreeSections((U16 *) &nSections);
   if (err != GOOD)
      return (err);
      /* put up dialog indicating load complete - OK */
   infotype = LD_COMPLETE;
   InfoMsg(infomsg[infotype], IM_DISPLAY);

/*
don't generate events, since callbacks aren't implemented
Need to discuss if they make sense for srec!!
    EnlEventNotify(EVENT_LDR_LOADCOMPLETE);
*/
   // Always free the sections part.
   return (GOOD);
}  /* SldLoadWin */

/*****************************************************************************
**
**  InitCServer
**
*****************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {
	CSERVER_NEW_REGISTRATION FAR *msgBufPtr;

	/* capture these */
	cliServerHandle = cliHandle;
	dllServerHandle = dllHandle;

   msgBufPtr = (CSERVER_NEW_REGISTRATION FAR *)
            TMalloc(sizeof(CSERVER_VARIABLE_VALUE));
   if (msgBufPtr == NULL) {
      return(ER_OUT_OF_MEMORY);
   }

   msgBufPtr->stringResourceHandle = dllHandle;

   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   /* no CLI commands! */
   msgBufPtr->commandStartIndex = 33;

   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);

   return(GOOD);
}  /* InitCServer */

/*****************************************************************************
**
**  Cleanup
**
*****************************************************************************/
/* When user decides to abort load operation, cleaup */
PRIVATE VOID Cleanup(U16 flags) {
   RETCODE symerr;
  
   if (LOAD_SYM(flags)) {
      if ((symerr = SymAddLoadEnd()) != GOOD) {
         Warning(symerr);
      }
      /* Remove all symbols */
      SymRemoveSymbols();  /* lets clean up */
   }
   // Always free Section info
   FreeSections((U16 *) &nSections);
}  /* Cleanup */

/********************************** E O F ***********************************/
