/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417)         $Workfile:: mfw_mfw.c       $|
| $Author:: Es  $ CONDAT GmbH           $Revision:: 11              $|
| CREATED: 21.09.98                     $Modtime:: 23.03.00 10:47   $|
| STATE  : code                                                      |
+--------------------------------------------------------------------+

   MODULE  : MFW_MFW

   PURPOSE : element chaining functions

   EXPORT  :

   TO DO   :

   $History:: mfw_mfw.c                                             $

      Nov 05, 2005	REF: OMAPS00049571   Sumanth Kumar. C
      Description:	eZi Text function is not working
      Solution:		current_mfw_elem variable is updated when any of the elements 
                            such as window, keyboard, timer, etc., are deleted so that the 
                            current_mfw_element does not point to element that has already been freed.

  	Feb 28, 2004    REF: CRR 25608     Deepa M.D
	The mfwEorc is made const.The changes will be present both in Color and Golite build .

      Jan 27, 2005 REF: CRR MMI-SPR-28300 xnkulkar
      Description: BMI: memory leak in mfwFree/mfwAlloc ??
      Solution: Trace output to print memory address and size freed  
                    modified in function mfwFree()
      
      Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
      Description: MFW memory size variable changed from U16 -> U32
      Solution: The use of variable U16 has been replaced with U32

      Oct 06, 2004    REF: CRR 25608     Deepa M.D
      Bug:Change "static MfwHdr mfwEorc =" to const
      Fix: MfwHdr mfwEorc is made const to save memory.
 *
 * *****************  Version 11  *****************
 * User: Es           Date: 23.03.00   Time: 14:43
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * Added 'mfwParent(elem)'
 *
 * *****************  Version 10  *****************
 * User: Es           Date: 18.02.00   Time: 15:45
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * fixed alloc/free bug (shrink)
 * changed MfwMemLarge macro
 * added constants for MMI event handler return values
 *
 * *****************  Version 9  *****************
 * User: Kk           Date: 10.01.00   Time: 14:03
 * Updated in $/GSM/Condat/MS/SRC/MFW
 *
 * *****************  Version 4  *****************
 * User: Rm           Date: 12/22/99   Time: 4:34p
 * Updated in $/GSM/Condat/SND-MMI/MFW
 *
 * *****************  Version 3  *****************
 * User: Be           Date: 29.11.99   Time: 14:31
 * Updated in $/GSM/Condat/SND-MMI/MFW
 * target integration
 *
 * *****************  Version 2  *****************
 * User: Es           Date: 22.11.99   Time: 10:24
 * Updated in $/GSM/Condat/SND-MMI/MFW
 *
 * *****************  Version 1  *****************
 * User: Es           Date: 18.11.99   Time: 16:35
 * Created in $/GSM/Condat/SND-MMI/MFW
 * Initial
 *
 * *****************  Version 6  *****************
 * User: Es           Date: 1.04.99    Time: 17:07
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * removed lots of traces
 *
 * *****************  Version 5  *****************
 * User: Es           Date: 18.02.99   Time: 17:01
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 4  *****************
 * User: Es           Date: 17.02.99   Time: 19:11
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 3  *****************
 * User: Es           Date: 27.01.99   Time: 15:06
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 2  *****************
 * User: Es           Date: 23.12.98   Time: 16:19
 * Updated in $/GSM/DEV/MS/SRC/MFW
*/
#define ENTITY_MFW

#define TRACE_MEMORY

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined (NEW_FRAME)

#include "typedefs.h"
#include "vsi.h"
#include "pei.h"
#include "custom.h"
#include "gsm.h"

#else

#include "STDDEFS.H"
#include "custom.h"
#include "gsm.h"
#include "vsi.h"

#endif

//#include <stdio.h>
//#include <string.h>

#include "mfw_mfw.h"
#include "mfw_sys.h"
#include "mfw_win.h"
#include "mfw_sat.h"	/* CQ16435 : Header Required */

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
U32 mfwMemDynTotal = 0;                 /* sample memory usage      */
U32 mfwMemLowWater = 0xffffffff;            /* sample memory usage      */

MfwHdr *mfwFocus = 0;                   /* the focus node           */
MfwHdr *mfwRoot = 0;                    /* root of MFW elements     */
MfwCb mfwCommand [MfwTypMax];           /* MFW commands to modules  */

static MfwHdr *mfwSatIdleWin = 0;	/* CQ16435 : When this window gets focus, SAT will be informed */

static MfwMemHdr mfwMem;                /* root of free memory list */
static U8 *mfwMemBase;                  /* mfw dynamic memory pool  */
static U8 *mfwMemEnd;                   /* end of mfw memory        */

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
static U32 mfwMemLeft;                  /* space left in pool       */

//Feb 28, 2005    REF: CRR 25608     Deepa M.D
//The mfwEorc is made const.The changes will be present both in Color and Golite build
static const  MfwHdr mfwEorc = {0, MfwTypMax, 0}; /* end of root chain     */
 

/***************************Go-lite Optimization changes end***********************/

U8     mfwSignallingMethod = 0;           /* default is focus+root    */

EXTERN MfwHdr * current_mfw_elem;

#define SENTINAL_CHECK 1

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: define SENTINEL_SIZE to a value of 4
#define SENTINEL_SIZE  4   //Will, Dec/07/2004-->Ti is 4 bytes
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwInit            |
+--------------------------------------------------------------------+

  PURPOSE : initialize framework

*/

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
MfwRes mfwInit (void *externalRoot, U32 dynMemSize)
{
    int i;

    mfwSetFocus(0);                       /* initially no focus       */
    dynMemSize &= ~(sizeof(MfwMemHdr)-1); /* align to header size   */
    mfwMemDynTotal = dynMemSize;
    if (dynMemSize)
    {
		
/***************************Go-lite Optimization changes start***********************/
        mfwRoot = (MfwHdr *)&mfwEorc;             /* points to end of chain   */
		
/***************************Go-lite Optimization changes end***********************/
        mfwMemBase = (U8 *) externalRoot; /* setup memory handler   */
        mfwMemEnd = (U8 *) externalRoot + dynMemSize;
        mfwMem.next = 0;
        mfwMem.len = 0;
        ((MfwMemHdr *) mfwMemBase)->next = dynMemSize;
        ((MfwMemHdr *) mfwMemBase)->len = dynMemSize;
        mfwMemLeft = dynMemSize;
        memset(mfwMemBase+sizeof(MfwMemHdr),0,
                                    dynMemSize-sizeof(MfwMemHdr));
    }
    else
    {
        mfwRoot = (MfwHdr *) externalRoot; /* setup root pointer    */
		
/***************************Go-lite Optimization changes start***********************/
        if (!mfwRoot)
            mfwRoot = (MfwHdr *)&mfwEorc;         /* points to end of chain   */
		
/***************************Go-lite Optimization changes end***********************/
        mfwMemBase = 0;
        mfwMemEnd = 0;
        mfwMem.next = 0;
        mfwMem.len = 0;
    }
    for (i = 0; i < MfwTypMax; i++)     /* init command table       */
        mfwCommand[i] = 0;

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwExit            |
+--------------------------------------------------------------------+

  PURPOSE : finalize framework

*/

void mfwExit (void)
{
    TRACE_FUNCTION("mfwExit()");
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwSignallingMethod|
+--------------------------------------------------------------------+

  PURPOSE : Defines the signalling method

*/

MfwRes mfwSetSignallingMethod (U8 method)
{
  mfwSignallingMethod = method;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwSetFocus          |
+--------------------------------------------------------------------+

  PURPOSE : Assign Focus to the passed window

*/

void mfwSetFocus(MfwHdr *w)
{
       if (satEvtRegistered(SatEvtIdleScreenActivated) == TRUE)
       {
		if ((mfwSatIdleWin != 0) && (mfwSatIdleWin == w))
		{
			TRACE_EVENT("NDH >>> CQ16435 : Send the Idle Screen Available Event to the SIM");
			satEvtDownload(SatEvtIdleScreen);
		}
       }

	mfwFocus = w;
	return;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwSetSatIdle          |
+--------------------------------------------------------------------+

  PURPOSE : Set the window which will trigger SAT Event Idle Activated if required

*/
void mfwSetSatIdle(MfwHdr *w)
{
	MfwWin *win;

	if (!w)
	{
		mfwSatIdleWin = 0;
		return;
	}

	win = w->data;

	mfwSatIdleWin = win->elems;
	return;
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwInsert          |
+--------------------------------------------------------------------+

  PURPOSE : chain up framework element

*/

MfwHdr *mfwInsert (MfwHdr *h, MfwHdr *e)
{
    if (!e)                             /* nothing to insert        */
        return 0;

    if (!h)                             /* use root chain           */
    {
        e->next = mfwRoot;
        mfwRoot = e;
    }
    else if (h->type == MfwTypWin)      /* use window chain         */
    {
        e->next = ((MfwWin *) (h->data))->elems;
        ((MfwWin *) h->data)->elems = e;
        if (mfwFocus == e->next)        /* was focus window ?       */
            mfwSetFocus(e);               /* yes: reassign focus      */
    }
    else                                /* insert into any chain    */
    {
      return 0;
    }

    return e;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwAppend          |
+--------------------------------------------------------------------+

  PURPOSE : chain up framework element at end of chain

*/

MfwHdr *mfwAppend (MfwHdr **h, MfwHdr *e)
{
    if (!e)                             /* nothing to append        */
        return 0;

    if (!h)                             /* append to header chain   */
        h = &mfwRoot;

    if ((*h)->type == MfwTypMax)        /* empty chain              */
    {
        if (mfwFocus == *h)
            mfwSetFocus(e);
        e->next = *h;
        *h = e;
        return e;
    }

    while ((*h)->next && (*h)->next->type != MfwTypMax)
        h = &((*h)->next);

    e->next = (*h)->next;
    (*h)->next = e;

    return e;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwRemove          |
+--------------------------------------------------------------------+

  PURPOSE : unchain element and return its root

*/

MfwHdr **mfwRemove (MfwHdr *e)
{
    MfwHdr **rp, **rpr, *h;

    if (!e)                             /* nothing to remove        */
        return 0;

    h = e;                              /* find elements root       */
    while (h->next && h->type != MfwTypMax)
        h = h->next;
    if (h->type != MfwTypMax)
        return 0;
    h = h->next;                        /* h points to root element */
    if (!h)                             /* remove from header chain */
        rp = &mfwRoot;
    else if (h->type == MfwTypWin)      /* remove from window chain */
        rp = &(((MfwWin*)(h->data))->elems);
    else                                /* don't remove from normal */
        return 0;

    rpr = rp;
    while (*rp && (*rp)->type != MfwTypMax)
    {
        if (*rp == e)
        {
            *rp = e->next;
            if (mfwFocus == e)          /* first element of window  */
                mfwSetFocus(e->next);
/*    Nov 05, 2005	REF: OMAPS00049571   Sumanth Kumar. C
  *    Solution: 	current_mfw_elem variable is updated when any of the elements 
  *                         such as window, keyboard, timer, etc., are deleted so that the 
  *                         current_mfw_element does not point to element that has already been freed.
  */			
            if(e->type == MfwTypWin || e->type == MfwTypKbd ||e->type == MfwTypTim ||
	         e->type == MfwTypEdt || e->type == MfwTypMnu || e->type == MfwTypIcn)
	             current_mfw_elem = e->next;
            return rpr;
        }
        rp = &((*rp)->next);
    }

    return 0;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwParent          |
+--------------------------------------------------------------------+

  PURPOSE : get parent of given element

*/

MfwHnd mfwParent (MfwHdr *h)
{
    if (!h)                             /* no element               */
        return 0;

    while (h->next && h->type != MfwTypMax)
    {
      h = h->next;
      if(!h)
      {
        return 0;
      }
    }
    if (h->type != MfwTypMax)
        return 0;                       /* ERROR !                  */
    h = h->next;                        /* h points to root element */
    if (h && h->type == MfwTypWin)      /* parent should be window  */
        return h;

    return 0;                           /* root element             */
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwHeader          |
+--------------------------------------------------------------------+

  PURPOSE : get header of a given element

*/

MfwHnd mfwHeader (void)
{
  return current_mfw_elem;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwControl         |
+--------------------------------------------------------------------+

  PURPOSE : retrieve element control block

*/

MfwHnd mfwControl (MfwHdr *h)
{
    if (!h)
        return 0;
    if (h->type <= MfwTypNone || h->type >= MfwTypMax)
        return 0;

    return h->data;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwAlloc           |
+--------------------------------------------------------------------+

  PURPOSE : alloc MFW memory

*/

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
U8 *mfwAlloc (U32 size)
{
    MfwMemHdr *p, *n, *l;
    U8 *data_ptr;

    if (!size)
    {
        TRACE_ERROR("mfwAlloc(): invalid memory request");
        return 0;
    }
    
#ifdef SENTINAL_CHECK
    if (!mfwMemBase)
    {
    	size += (SENTINEL_SIZE*2);
    	data_ptr = (U8 *) sysAlloc(size);
    	memset(data_ptr, 0x55, SENTINEL_SIZE);
    	memset(data_ptr + (size-SENTINEL_SIZE), 0x55, SENTINEL_SIZE);
    	data_ptr += SENTINEL_SIZE;
        return data_ptr;
    }

   	size = (U32) mfwMemLarge(size) + (SENTINEL_SIZE*2);

    if (size >= mfwMemLeft)
    {
        TRACE_ERROR("mfwAlloc(): no memory");
        return 0;
    }
    
    if (mfwMemBase + mfwMem.next > mfwMemEnd
              || mfwMemBase + mfwMem.next < mfwMemBase)
    {
        TRACE_ERROR("mfwAlloc(): corrupted memory");
        return 0;
    }

    p = &mfwMem;                        /* root of dyn memory       */
    n = (MfwMemHdr *) (mfwMemBase + p->next); /* first free block   */
    while ((U8 *) n < mfwMemEnd)
    {
        if (n->len == size)             /* fits exactly:            */
        {
            p->next = n->next;          /* just remove from chain   */

            mfwMemLeft -= size;
            if (mfwMemLeft < mfwMemLowWater)
                mfwMemLowWater = mfwMemLeft;

			data_ptr = (U8 *)n;

            memset(data_ptr, 0x55, SENTINEL_SIZE);
            memset(data_ptr + size-SENTINEL_SIZE, 0x55, SENTINEL_SIZE);
            memset(data_ptr + SENTINEL_SIZE, 0, size-(SENTINEL_SIZE*2));

            data_ptr += SENTINEL_SIZE;

#ifdef TRACE_MEMORY
            TRACE_EVENT_P2("MFWAlloc %d bytes in address %p",size,n);
            mfwCheckMemoryLeft();
#endif
            return data_ptr;
        }

        if (n->len > size)              /* take it from a big one   */
        {
            l = (MfwMemHdr *) ((U8 *) n + size); /* new header    */
            l->next = n->next;          /* setup chain to next    */
            l->len = (U32) (n->len - size); /* remaining memory   */
            p->next += size;            /* link with previous block */

            mfwMemLeft -= size;
            if (mfwMemLeft < mfwMemLowWater)
                mfwMemLowWater = mfwMemLeft;

			data_ptr = (U8 *)n;

            memset(data_ptr, 0x55, SENTINEL_SIZE);
            memset(data_ptr + size-SENTINEL_SIZE, 0x55, SENTINEL_SIZE);
            memset(data_ptr + SENTINEL_SIZE, 0, size-(SENTINEL_SIZE*2));

            data_ptr += SENTINEL_SIZE;

#ifdef TRACE_MEMORY
            TRACE_EVENT_P2("MFWAlloc %d bytes in address %p",size,n);
            mfwCheckMemoryLeft();
#endif
            return data_ptr;            /* allocated me address     */
        }
        p = n;
        n = (MfwMemHdr *) (mfwMemBase + n->next);
    }
#else
    if (!mfwMemBase)
        return (U8 *) sysAlloc(size);

    size = (U32) mfwMemLarge(size);
    if (size >= mfwMemLeft)
    {
        TRACE_ERROR("mfwAlloc(): no memory");
        return 0;
    }
    
    if (mfwMemBase + mfwMem.next > mfwMemEnd
              || mfwMemBase + mfwMem.next < mfwMemBase)
    {
        TRACE_ERROR("mfwAlloc(): corrupted memory");
        return 0;
    }

    p = &mfwMem;                        /* root of dyn memory       */
    n = (MfwMemHdr *) (mfwMemBase + p->next); /* first free block   */
    while ((U8 *) n < mfwMemEnd)
    {
        if (n->len == size)             /* fits exactly:            */
        {
            p->next = n->next;          /* just remove from chain   */
            mfwMemLeft -= size;
            if (mfwMemLeft < mfwMemLowWater)
                mfwMemLowWater = mfwMemLeft;
            memset(n,0,size);
#ifdef TRACE_MEMORY
            TRACE_EVENT_P2("MFWAlloc %d bytes in address %p",size,n);
            mfwCheckMemoryLeft();
#endif
            return (U8 *) n;
        }
        if (n->len > size)              /* take it from a big one   */
        {
            l = (MfwMemHdr *) ((U8 *) n + size); /* new header    */
            l->next = n->next;          /* setup chain to next    */
            l->len = (U32) (n->len - size); /* remaining memory   */
            p->next += size;            /* link with previous block */
            mfwMemLeft -= size;
            if (mfwMemLeft < mfwMemLowWater)
                mfwMemLowWater = mfwMemLeft;
            memset(n,0,size);
#ifdef TRACE_MEMORY
            TRACE_EVENT_P2("MFWAlloc %d bytes in address %p",size,n);
            mfwCheckMemoryLeft();
#endif
            return (U8 *) n;            /* allocated me address     */
        }
        p = n;
        n = (MfwMemHdr *) (mfwMemBase + n->next);
    }
#endif

    if ((U8 *)n == mfwMemEnd)
	{
    	TRACE_ERROR("mfwAlloc(): no memory block big enough to allocate size requested");
	}
    else
	{
    	TRACE_ERROR("mfwAlloc(): Error: free list corruption is likely");
	}

    return 0;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW                |
| STATE   : code                        ROUTINE : mfwFree            |
+--------------------------------------------------------------------+

  PURPOSE : free allocated MFW memory

*/

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
void mfwFree (U8 *mem, U32 size)
{
    MfwMemHdr *p, *n;
    U8 check_val[SENTINEL_SIZE];
//    U32 check_val = 0x55555555;

	memset(&check_val, 0x55, SENTINEL_SIZE);

#ifdef SENTINAL_CHECK
	mem -= SENTINEL_SIZE;
#endif

    if (!size || !mem )
    {
        TRACE_ERROR("mfwFree(): invalid");
        return;                         /* nothing to free          */
    }

#ifdef SENTINAL_CHECK
	/*
	** Check the 4 preceeding bytes to ensure they haven't been changed
	*/
	if (memcmp(mem, &check_val, SENTINEL_SIZE) != 0)
	{
    	TRACE_ERROR("mfwFree(): Error: Preceeding Sentinal Bytes have been corrupted");
	}
#endif

#ifdef TRACE_MEMORY
// Jan 27, 2005 REF: CRR MMI-SPR-28300 xnkulkar
// Description: BMI: memory leak in mfwFree/mfwAlloc ??
// Solution: Trace output to print memory address and size freed modified 
    TRACE_EVENT_P2("MFWFree address = %p, size : %d bytes",mem,size);
#endif

    if (!mfwMemBase)
    {
        void *m = mem;
        
#ifdef SENTINAL_CHECK
		/*
		** Check the SENTINEL_SIZE last bytes to ensure they haven't been changed
		*/
		if (memcmp(mem + size + SENTINEL_SIZE, &check_val, SENTINEL_SIZE) != 0)
		{
	    	TRACE_ERROR("mfwFree(): Error: Following Sentinal Bytes have been corrupted");
		}
#endif
        sysFree(m);
        return;
    }

#ifdef SENTINAL_CHECK

	size = (U32) mfwMemLarge(size) + (SENTINEL_SIZE*2);
#else
    size = (U32) mfwMemLarge(size);
#endif

    if ( mem < mfwMemBase || mem >= mfwMemEnd ||
       mem + size > mfwMemEnd ||
       mem + size <= mfwMemBase)
    {
        TRACE_ERROR("mfwFree(): invalid");
        return;                         /* nothing to free          */
    }

    p = &mfwMem;                        /* root of dyn memory       */
    n = (MfwMemHdr *) (mfwMemBase + p->next); /* first free block   */

	/*
	** Skip through the Free Link List until we get to where the current pointer
	** should be added
	*/
    while ((U8 *) n < mfwMemEnd && (U8 *) n < mem)
    {                                   /* search allocated area    */
        p = n;
        n = (MfwMemHdr *) (mfwMemBase + n->next);
    }

    /*
    ** Check that the select memory isn't already free
    */
    if (mem == (U8 *) p || mem == (U8 *) n)
    {
        TRACE_ERROR("mfwFree(): already free");
        return;                         /* already free             */
    }

	/*
	** Memory not already free
	*/
        
#ifdef SENTINAL_CHECK
		/*
		** Check the 4 last bytes to ensure they haven't been changed
		*/
		if (memcmp(mem + size - SENTINEL_SIZE, &check_val, SENTINEL_SIZE) != 0)
		{
	    	TRACE_ERROR("mfwFree(): Error: Following Sentinal Bytes have been corrupted");
		}
#endif

	/*
	** This memset should only be performed after we are sure that the memory should be freed
	*/
    memset(mem, 0, size);

    if (p != &mfwMem && (U8 *) p + p->len == mem)
    {                                   /* adjacent to left free:   */
        p->len += size;                 /* just add it              */
    }
    else
    {
        p->next = (U32) (mem - mfwMemBase); /* new free link        */
        p = (MfwMemHdr *) mem;          /* to new header            */
        p->next = (U32) ((U8 *) n - mfwMemBase); /* link to next    */
        p->len = size;
    }

    if ((U8 *) n < mfwMemEnd && ((mem + size) == (U8 *) n))
    {                                   /* adjacent to right free:  */
        p->next = n->next;              /* eliminate link and       */
        p->len += n->len;               /* eat up the space         */
    }

    mfwMemLeft += size;
#ifdef TRACE_MEMORY
            mfwCheckMemoryLeft();
#endif
}

// Dec 22, 2004 REF: CRR MFW-SPR-27847 xnkulkar
// Description: MFW memory size variable changed from U16 -> U32
// Solution: The use of variable U16 has been replaced with U32
U32 mfwCheckMemoryLeft(void)
{
  TRACE_EVENT_P1("memory left %ld",mfwMemLeft);

  return mfwMemLeft;
}

/*
** This function gives the bounds safety of strncpy, but NULL terminates the string like strcpy
** 
** parameters : cpyto : the pointer to the destination string
**                   : cpyfrm : the pointer to the source string
**                   : len : the maximum length of the destination string including the NULL terminator
**
** returns        : A character pointer to the destination string if successful, otherwise NULL
**
** CQ16507      : strcpy call for string without null termination causing hardware reset
*/

char *mfwStrncpy(char *cpyto, const char *cpyfrm, size_t len)
{

	if (len <= 0)
		return (void *)0;

	if (cpyto == (char *)0)
		return (void *)0;

	strncpy(cpyto, cpyfrm, len-1);

	*(cpyto + (len -1)) = 0x00;

	return cpyto;
}

