view src/gpf3/ccd/csn1_sx.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 c41a534f33c6
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project : CCD
|  Modul   : csn1_sx.c
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  Definition of encoding and decoding functions for CSN1_S0 elements
+----------------------------------------------------------------------------- 
*/
/*
 * standard definitions like GLOBAL, UCHAR, ERROR etc.
 */
#include "typedefs.h"
#include "header.h"


/*
 * Prototypes of ccd (USE_DRIVER EQ undef) for prototypes only
 * look at ccdapi.h
 */
#undef USE_DRIVER
#include "ccdapi.h"

/*
 * Types and functions for bit access and manipulation
 */
#include "ccd_globs.h"
#include "bitfun.h"

/*
 * Prototypes of ccd internal functions
 */
#include "ccd.h"

/*
 * Declaration of coder/decoder tables
 */
#include "ccdtable.h"
#include "ccddata.h"

/*
 * Need memory allocation functions for dynamic arrays (pointers)
 */
#ifdef DYNAMIC_ARRAYS
#include "vsi.h"
#include <string.h>
#endif


#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)               MODULE  : CCD                   |
| STATE   : code                     ROUTINE : cdc_csn1_sx_decode    |
+--------------------------------------------------------------------+

  PURPOSE : The encoded IE consists of one bit for presence flag and 
            a value part. 
            In case of CSN1_S1 only if the flag bit is equal 1 the  
            value part will follow it.
            In case of CSN1_S0 only if the flag bit is equal 0 the 
            value part will follow it.
*/

SHORT cdc_csn1_sx_decode (int flag, const ULONG e_ref, T_CCD_Globs *globs)
{
  ULONG  repeat, max_rep, act_offset;
  ULONG  amount = 1;
  BOOL   is_variable;
  ULONG  cix_ref, num_prolog_steps, prolog_step_ref;
#ifdef DYNAMIC_ARRAYS
  U8     *old_pstruct = NULL;
  U8     *addr = NULL;
#endif

#ifdef DEBUG_CCD
  #ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_csn1_sx_decode()");
	#else
	TRACE_CCD (globs, "cdc_csn1_sx_decode() %s", ccddata_get_alias((USHORT) e_ref, 1));
	#endif
#endif

  globs->SeekTLVExt = FALSE;
  
  cix_ref = melem[e_ref].calcIdxRef;
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;

  /*
   * If this element is conditional, check the condition.
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return 1;

  /*
   * If this element has a defined prologue
   * we have to process it before decoding the bitstream.
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  if (melem[e_ref].repType NEQ ' ')
  {
    is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs);
    /* Structured IE is to be handeled as bitstring.*/
    if (melem[e_ref].repType == 's')
    {
      repeat--;
    }
  }
  else
  {
    is_variable = FALSE;
    repeat     = 1;
  }

#ifdef DYNAMIC_ARRAYS
  /*
   * Check for pointer types; allocate memory if necessary.
   * May overwrite globs->pstruct (and initialize globs->pstructOffs to 0).
   */
  if ( is_pointer_type(e_ref) ) 
  {
    U32     cSize;

    /*
     * Find size to allocate;
     * - Read from mcomp or mvar according to type
     */
    cSize = (ULONG)((melem[e_ref].elemType EQ 'F' OR
		      melem[e_ref].elemType EQ 'R')
                     ? mvar[melem[e_ref].elemRef].cSize
                     : mcomp[melem[e_ref].elemRef].cSize
		     ) * repeat;

    /*
     * Allocate additional memory
     */
    addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS);

    /* If no memory, log error and return immediately */
    if (addr EQ NULL) {
      ccd_setError (globs, ERR_NO_MEM,
                    BREAK,
                    (USHORT) -1);
      return 1;
    }
    else
      memset (addr, 0, (size_t)cSize);

    /*
     * Memory allocated;
     */
  }
#endif
    
  if (melem[e_ref].elemType NEQ 'S')
  {
    /*
     * Element is not a SPARE. Setup the struct pointer.
     */
    globs->pstructOffs = melem[e_ref].structOffs;


    if (is_variable)
    {
      UBYTE *addr_v_xxx = NULL;
      UBYTE *addr_c_xxx;
      UBYTE  act_continue_array;
  

      if (melem[e_ref].optional)
      {
        /*
         * For optional elements we must set the valid-flag,
         * if there is at least one element in the message.
         * Therefore we store the address of the valid flag.
         */
        /* Dynamic array addition.
         * Postpone optional flag setting for non-code transparent
         * pointer types ('P', 'Q', 'R').
         * For these types, the optional flag is the pointer itself.
         * These types cannot be set yet, as the pointer may be
         * preceeded by a counter octet, a union tag id octet etc.
         */
        if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R')
        addr_v_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++);
      }
      /*
       * For variable sized elements store the min-value
       * as counter into the C-Structure (c_xxx).
       */
      addr_c_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++);
      if (max_rep > 255)
        globs->pstructOffs++;      
      
      /*
       * Store the initial offset
       */

      act_offset = (ULONG) globs->pstructOffs;

#ifdef DYNAMIC_ARRAYS
    if ( is_pointer_type(e_ref) ) 
    {
      /*
       * 1. Save old "globs->pstruct" variables
       * 2. Store pointer to freshly allocated memory area in structure
       * 3. Initialize pstruct to point to the freshly allocated memory area.
       * 4. Initialize pstructOffs to 0 to start decoding at offset 0
       *    in the new memory area.
       */
      old_pstruct        = globs->pstruct;
      *(U8 **)(globs->pstruct + globs->pstructOffs) = addr;
      globs->pstruct     = addr;
      globs->pstructOffs = 0;
    }
#endif

      /*
       * repType ='i':
       * Repeat this element (if it is an array) until we detect a 
       * flag indicating absence.
       *
       * repType ='v' and 'c':
       * Repeat the IE and leave the loop.
       *
       * In both cases we expect a 0 at first.
       */
      if ((melem[e_ref].repType == 'v') || (melem[e_ref].repType == 'c'))
      {
        amount = repeat;
      }
      repeat = 0;
      act_continue_array = globs->continue_array;
      globs->continue_array = TRUE;

      while (globs->continue_array)
      {
        if (flag == 0xFF) /* CSN1_SH type*/
        {
          if (bf_readBit(globs) != GET_HL_PREV(1))
            break;
        }
        else
        {
          if (bf_readBit(globs) != flag)
            break;
        }
          /*
           * Flag is set, we must decode the element
           */
  
          cdc_decodeElemvalue (e_ref, &amount, globs);

          if (++repeat > max_rep)
          {
            /*
             * Too many repetitions means error in encoded message.
             */
            ccd_setError (globs, ERR_MAX_REPEAT,
                          BREAK,
                          (USHORT) (globs->bitpos),
                          (USHORT) -1);
            return 1;
          }
          else if (melem[e_ref].repType EQ 'v')
          {
            repeat = amount;
            break;
          }
          /*
           * Recalculate the struct offset for repeatable IEs.
           */
          if (is_variable_type(e_ref))
          {
            globs->pstructOffs = (USHORT)(act_offset + 
                                 (repeat * mvar[melem[e_ref].elemRef].cSize));
          }
          else
          {
            globs->pstructOffs = (USHORT)(act_offset +
                                 (repeat * mcomp[melem[e_ref].elemRef].cSize));
          }
        }
      globs->continue_array = act_continue_array;
              
#ifdef DYNAMIC_ARRAYS
      /*
       * Restore globs->pstruct 
       */
      if (old_pstruct NEQ NULL)
      {
        globs->pstruct     = old_pstruct;
      }
#endif

      if (addr_v_xxx NEQ NULL)
      {
        /*
         * For optional elements set the valid-flag
         * In this case the pointer addr_c_xxx does not mark
         * the counter. It points to the valid flag.
         */
        if (repeat > 0)
          *addr_v_xxx++ = (UBYTE) TRUE;
      }
      /*
       * Store the number of digits into the c_xxx variable if there is one.
       */
      if (max_rep > 65535)
      {
       ULONG *addr_c_xxx_u32;
       addr_c_xxx_u32 = (ULONG *)addr_c_xxx;
       *addr_c_xxx_u32 = repeat;
      }
      else if (max_rep > 255)
      {
        USHORT *addr_c_xxx_u16;
        addr_c_xxx_u16 = (USHORT *)addr_c_xxx;
        *addr_c_xxx_u16 = (USHORT) repeat;
      }
      else
        *addr_c_xxx = (UBYTE) repeat;
    }
    /*
     * IE is not defined as an array.
     */
    else
    {
      BOOL  elemPresent;

      if (flag == 0xFF)     
        elemPresent = (bf_readBit(globs) EQ GET_HL_PREV(1));
      else 
        elemPresent = (bf_readBit(globs) == flag);
        
      if (elemPresent)
      {
        if (melem[e_ref].optional)
        {
          /*
           * For optional elements set the valid-flag.
           */
            globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE;
        }
        
        /*
         * Flag is set, we must decode the element.
         */
        cdc_decodeElemvalue (e_ref, &repeat, globs);
        /*
         * process the epilogue expression for this element if there is any 
         */
        if (num_prolog_steps)
        {
          if (  (calc[prolog_step_ref+1].operation EQ 'K')
             || (calc[prolog_step_ref+1].operation EQ 'C')
             || (calc[prolog_step_ref+1].operation EQ 's'))
          {
            ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
          }
        }
      }
    }
  }

  return 1;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_GSM                |
| STATE   : code                    ROUTINE : cdc_csn1_sx_encode     |
+--------------------------------------------------------------------+

  PURPOSE : Encoding of the CSN1 element.
            1) GSM Type CSN1 S1 element
               This element consists of a 1 bit valid flag and a 
               value part. If the element is valid (the v_xxx 
               components is TRUE in the decoded message) a 1 bit will
               be coded followed by the coding of the value part.
               Otherwise a 0 bit will be coded.

            2) GSM Type CSN1 S0 element
               This element consists of a single bit valid flag and a 
               value part, too. But in this case the presence flag is
               set to 0. If the element is present (the v_xxx component
               is TRUE in the decoded message) a 0 bit will be coded 
               followed by the encoded value part. Otherwise a 1 bit
               will be encoded.
*/

SHORT cdc_csn1_sx_encode (int flag, const ULONG e_ref, T_CCD_Globs *globs)
{
  ULONG  i, repeat=1, amount=1;
  USHORT cSize = 0, startOffset;
  int    elemPresent;
  ULONG  cix_ref, num_prolog_steps, prolog_step_ref;
#ifdef DYNAMIC_ARRAYS
  U8     *old_pstruct = NULL;
#endif

#ifdef DEBUG_CCD
  #ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_csn1_sx_encode()");
	#else
	TRACE_CCD (globs, "cdc_csn1_sx_encode() %s", ccddata_get_alias((USHORT) e_ref, 1));
	#endif
#endif

  cix_ref = melem[e_ref].calcIdxRef;
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;
  /*
   * If this element is conditional, check the condition.
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return 1;

  /*
   * If this element has a defined prologue
   * we have to process it before decoding the bitstream.
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  if (melem[e_ref].elemType NEQ 'S')
  {
    UBYTE act_continue_array;

    act_continue_array = globs->continue_array;
    globs->continue_array = TRUE;
    /*
     * Element is not a SPARE.
     * Setup the offset into the C-structure for this element
     */
    globs->pstructOffs = melem[e_ref].structOffs;

    if (melem[e_ref].optional)
    {  
      /*
       * For optional elements check the valid-flag in the C-struct.
       * Spare elements does not have a corresponding valid flag.
       */
      /* Dynamic array addition.
       * Postpone optional flag setting for non-code transparent
       * pointer types ('P', 'Q', 'R').
       * For these types, the optional flag is the pointer itself.
       * These types cannot be set yet, as the pointer may be
       * preceeded by a counter octet, a union tag id octet etc.
       */
      if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R')
      {
        if (globs->pstruct[globs->pstructOffs++] == FALSE)
        {
          /*
           * The IE should not be present in the message so we code
           * a single bit
           * for CSN1_S1 as 0,
           * for CSN1_S0 as 1 and
           * for CSN1_SH as GET_HL(0)
           */
          if (flag == 0xFF)
            elemPresent = GET_HL(0);
          else
            elemPresent = flag ^ 0x00000001;
          bf_writeBit (elemPresent, globs);
          return 1;
        }
#ifdef DEBUG_CCD
        else if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
        {
          TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d",
                     e_ref);
        }
#endif
      }
    }

    /* As a default amount =1 due to initialization. */
    if (melem[e_ref].repType EQ 'i')
    {
      /* The actual number of elements belonging to the array is unknown.
       * The user should have written the desired number to the C-Structure
       * (c_xxx). CCD reads the number of these variable repeatable elements
       * out of this C-Structure (c_xxx) and encodes each element with a
       * preceeding bit set to '0'. The last element is followed by a bit
       * set to '1' to indicate the end of this array. 
       * If the number of repeats given by the C-Structure exceeds the 
       * allowed value (maxRepeat) CCD gives a warning!
       */
      if (melem[e_ref].maxRepeat > 255)
      {
        ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++));
        repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat);
        if (repeat < count) 
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      else
      {
        repeat = (ULONG) MINIMUM (globs->pstruct[globs->pstructOffs], 
                                  melem[e_ref].maxRepeat);
        if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) )
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      amount = 1;
      globs->pstructOffs++;
    }
    else
    if (melem[e_ref].repType EQ 'v')
    {
      /* The number of elements belonging to the array depends on the value 
       * of another element. The user should have written this number to the 
       * C-Structure (c_xxx).
       * CCD reads the number of these variable repeatable elements out of 
       * this C-Structure (c_xxx).
       * If the number of repetitions given by the C-Structure exceeds the
       * allowed value (maxRepeat) CCD gives a warning!
       */
      if (melem[e_ref].maxRepeat > 255)
      {
        ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++));
        amount = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat);
        if (amount < count) 
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      else
      {
        amount = (ULONG)MINIMUM (globs->pstruct[globs->pstructOffs], 
                                  melem[e_ref].maxRepeat);
        if ( amount < (ULONG) (globs->pstruct[globs->pstructOffs]) )
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      repeat = 1;
      globs->pstructOffs++;
    }
    else
    if (melem[e_ref].repType EQ 'c')
    {
      amount = (ULONG) melem[e_ref].maxRepeat;
      repeat = 1;
    }
    else
    if (melem[e_ref].repType == 's')
    {
      BOOL  is_variable;
      ULONG max_rep;
      
      is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs);
      /* Substract one bit which will be spent on the (CSN.1) flag. */
      amount = repeat - 1;
      repeat = 1;
    }
    if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i')
    {
      cSize = (USHORT)((melem[e_ref].elemType EQ 'V' OR
		      melem[e_ref].elemType EQ 'R' OR melem[e_ref].elemType EQ 'F')
                 ? mvar[melem[e_ref].elemRef].cSize
                 : mcomp[melem[e_ref].elemRef].cSize
              );
      
      startOffset = (USHORT) globs->pstructOffs;
    }
    
    /* Dynamic array addition.
     * Check for non-code transparent pointer types ('P', 'Q', 'R').
     * For these types, the optional flag is the pointer itself.
     * ASSUMPTION: The pointer may be preceeded by a counter octet,
     * a union tag id octet etc., but it is up to CCDGEN to ensure
     * word alignment (by inserting alignment bytes). Therefore
     * we just read from globs->pstruct[globs->pstructOffs].
    */
#ifdef DEBUG_CCD
    /* Check pointer alignment and re-align if necessary (should never happen) */
    if ( is_pointer_type(e_ref) AND ((globs->pstructOffs & 3) NEQ 0)) {
      TRACE_CCD (globs, "cdc_csn1_sx_encode(): Pointer misaligned! pstruct=0x08x,"
		 " pstructOffs=0x%08x", globs->pstruct, globs->pstructOffs);
      globs->pstructOffs = (globs->pstructOffs + 3) & 3;
    }
#endif
#ifdef DYNAMIC_ARRAYS
    /*
     * Perform pointer dereference for pointer types.
     * Also, check optionality for these types.
     */
    if ( is_pointer_type(e_ref) ) {
      U8 *deref_pstruct;

      /* Get pointer value */
      deref_pstruct = *(U8 **)&globs->pstruct[globs->pstructOffs];

      /*
       * Strictly speaking the 'D' to 'F' types should not need this
       * check (should have returned after the optionality check above),
       * but it will catch stray NULL pointers (or uninitialized
       * valid flags)
      */
      if (ccd_check_pointer(deref_pstruct) != ccdOK )
      {
        ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, 
                         &globs->pstruct[globs->pstructOffs]);
        return 1;
      }
      /*
       * Pointer not NULL;
       * 1. Save old globs->pstruct and assign pointer to globs->pstruct
       *    as new base.
       * 2. Set pstructOffs to 0 (zero) as the next offset will start
       *    in the new memory area.
       */
      old_pstruct        = globs->pstruct;
      globs->pstruct     = deref_pstruct;
      startOffset        = 0;
    }
#endif /* DYNAMIC_ARRAYS */
  
    for (i=0; i < repeat; i++)
    {
      /*
       * The IE should be present in the message so we code 0 bit.
       */
      if (flag == 0xFF)
        elemPresent = GET_HL(1);
      else
        elemPresent = flag;
        
      bf_writeBit (elemPresent, globs);
      if (cSize)
      {
        /*
         * Calculate the offset if it is an array.
         */
        globs->pstructOffs = (USHORT)(startOffset + (i * cSize));
      }
      /*
       * Encode the value.
       */
      cdc_encodeElemvalue (e_ref, amount, globs);
    }

#ifdef DYNAMIC_ARRAYS
  if ( old_pstruct NEQ NULL )
    globs->pstruct = old_pstruct;
#endif

    if ((melem[e_ref].repType == 'i') && (globs->continue_array == TRUE))
    {
      /*
       * For fields of variable length we code a 1 flag
       * to mark the end of the array.
       */
      if (flag == 0xFF)
        elemPresent = GET_HL(0);
      else
        elemPresent = flag ^ 0x00000001;
      bf_writeBit (elemPresent, globs);
    }
    globs->continue_array = act_continue_array;
  }

  return 1;
}
#endif /* !RUN_FLASH */