view src/aci2/mfw/mfw_mfw.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 93999a60b835
children
line wrap: on
line source

/*
+--------------------------------------------------------------------+
| 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;
}