diff comlib/cl_imei.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children c0f2d21307d1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/comlib/cl_imei.c	Thu Jun 09 00:02:41 2016 +0000
@@ -0,0 +1,283 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :  COMLIB
+|  Modul   :  cl_imei.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 :  Definitions of common library functions: IMEI decryption with
+              DES algorithm
++-----------------------------------------------------------------------------
+*/
+/*
+ *  Version 1.0
+ */
+
+/**********************************************************************************/
+
+/*
+NOTE:
+*/
+
+/**********************************************************************************/
+
+#ifndef CL_IMEI_C
+#define CL_IMEI_C
+
+#include "config.h"
+#include "fixedconf.h"
+
+#include "typedefs.h"
+#include "vsi.h"        /* to get a lot of macros */
+
+#include "../services/ffs/ffs.h"
+#include "../bsp/mem.h"
+#include "pcm.h"
+
+#include "cl_imei.h"
+#include "cl_des.h"
+#include <string.h>
+
+static UBYTE stored_imei[CL_IMEI_SIZE]; /* when the imei is read once, the value
+                                             is stored in this buffer */
+static UBYTE imei_flag = 0;  /* this flag indicates, if IMEI was successful read
+                                and is  stored in the stored_imei buffer */
+
+/* Default IMEISV for D-Sample 00440000-350-111-20 */
+const  UBYTE C_DEFAULT_IMEISV_DSAMPLE[CL_IMEI_SIZE] =
+             {0x00, 0x44, 0x00, 0x00, 0x35, 0x01, 0x11, 0x20};
+#define CL_IMEI_FFS_PATH   "/etc/IMEISV"
+
+/*==== FUNCTIONS ==================================================*/
+
+#if CONFIG_TARGET_PIRELLI
+/*
++------------------------------------------------------------------------------
+| Function    : get_dieID
++------------------------------------------------------------------------------
+| Description : the function reads the Die-ID from base band processor and
+|               extracts it from 4 BYTEs to 8 BYTEs.
+|
+| Parameters  : inBufSize  - size of buffer where to store Die ID, min.8 BYTE
+|               *outBufPtr - pointer to buffer where to store the Die ID
+| Return      : void
++------------------------------------------------------------------------------
+*/
+LOCAL void get_dieID(USHORT inBufSize, UBYTE *outBufPtr)
+{
+  int i;
+  USHORT *outBuf16 = (USHORT*)&outBufPtr[0];
+  volatile USHORT *reg_p = (USHORT *) CL_IMEI_DIE_ID_REG;
+
+  TRACE_FUNCTION("get_dieID()");
+
+  if(inBufSize < CL_IMEI_DIE_ID_SIZE){
+    TRACE_ERROR("CL IMEI ERROR: buffer size for Die ID to short!");
+  }
+#ifdef IMEI_DEBUG
+  TRACE_EVENT_P1("CL IMEI INFO: Die-ID address(0x%x)", CL_IMEI_DIE_ID_REG);
+#endif
+  for (i = 0; i < CL_IMEI_DIE_ID_SIZE; i++) {
+    /* Die ID is 4 BYTE long, extract it to 8 BYTE. */
+    outBuf16[i] = (USHORT)(*(UINT8*)(reg_p)++);
+  }
+}
+
+extern int pirelli_read_factory_record(uint32 offset, void *userbuf,
+					T_FFS_SIZE size, int has_chksum);
+
+#define	PIRELLI_IMEI_OFFSET	0x504
+
+/*
++------------------------------------------------------------------------------
+| Function    : pirelli_get_imeisv
++------------------------------------------------------------------------------
+| Description : This function attempts to read and decrypt a valid IMEISV
+|		record from Pirelli's factory data block.
+|
+| Parameters  : inBufSize  - size of buffer where to store IMEI, min. 8 BYTE
+|               *outBufPtr - pointer to buffer where to store the IMEI
+| Return      :              0 - OK
+|                           <0 - ERROR
++------------------------------------------------------------------------------
+*/
+LOCAL BYTE pirelli_get_imeisv (USHORT inBufSize, UBYTE *outBufPtr)
+{
+  UBYTE isdid_buf[CL_IMEI_ISDID_SIZE];
+  UBYTE r_dieId[CL_DES_KEY_SIZE]; /* read Die ID */
+  UBYTE d_dieId[CL_DES_KEY_SIZE]; /* deciphered Die ID */
+  SHORT ret;
+
+  TRACE_FUNCTION("pirelli_get_imeisv()");
+
+  if(inBufSize < CL_IMEI_SIZE){
+    TRACE_ERROR("CL IMEI ERROR: buffer size for IMEI to short!");
+    return CL_IMEI_ERROR;
+  }
+
+  /*
+   * Read ISDID(enciphered IMEISV+DieID) from FFS.
+   * (changed to read from Pirelli's factory data block instead)
+   */
+  if((ret = pirelli_read_factory_record(PIRELLI_IMEI_OFFSET, isdid_buf,
+					CL_IMEI_ISDID_SIZE, 0)) >= EFFS_OK)
+  {
+   /*
+    * Read Die ID for using as DES key
+    */
+    get_dieID(CL_DES_KEY_SIZE, r_dieId);
+   /*
+    * Call DES algorithm routine
+    */
+    /* decipher first 8 BYTEs */
+    cl_des(&isdid_buf[0], r_dieId, outBufPtr, CL_DES_DECRYPTION);
+    /* decipher the rest 8 BYTEs */
+    cl_des(&isdid_buf[CL_DES_BUFFER_SIZE], r_dieId, d_dieId, CL_DES_DECRYPTION);
+    if(!memcmp(d_dieId, r_dieId, CL_DES_KEY_SIZE))
+    {
+      /* Die ID is valid  */
+      ret = CL_IMEI_OK;
+    } else {/* Die ID is corrupted */
+      char pr_buf[126];
+      TRACE_ERROR("CL IMEI ERROR: Die ID is corrupted");
+      sprintf(pr_buf,"Read DieID: %02x %02x %02x %02x %02x %02x %02x %02x",
+                      r_dieId[0], r_dieId[1], r_dieId[2], r_dieId[3],
+                      r_dieId[4], r_dieId[5], r_dieId[6], r_dieId[7]);
+      TRACE_ERROR(pr_buf);
+      sprintf(pr_buf,"Deciphered DieID: %02x %02x %02x %02x %02x %02x %02x %02x",
+                      d_dieId[0], d_dieId[1], d_dieId[2], d_dieId[3],
+                      d_dieId[4], d_dieId[5], d_dieId[6], d_dieId[7]);
+      TRACE_ERROR(pr_buf);
+
+      ret = CL_IMEI_INVALID_DIE_ID;
+    }
+  } else {
+    ret = CL_IMEI_READ_IMEI_FAILED;
+  }
+
+  return ret;
+
+}/* pirelli_get_imeisv() */
+#endif	/* CONFIG_TARGET_PIRELLI */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : cl_get_imeisv
++------------------------------------------------------------------------------
+| Description : Common IMEI getter function
+|
+| Parameters  : imeiBufSize  - size of buffer where to store IMEI, min 8 BYTEs
+|               *imeiBufPtr  - pointer to buffer where to store the IMEI
+|               imeiType     - indicates, if the IMEI should be read from
+|                              FFS/Secure ROM (value=CL_IMEI_GET_SECURE_IMEI) or
+|                              if the already read and stored IMEI (if available)
+|                              should be delivered (value=CL_IMEI_GET_STORED_IMEI)
+|                              The second option should be used only by ACI or
+|                              BMI to show the IMEISV on mobile's display or
+|                              in terminal window, e.g. if user calls *#06#.
+|                              For IMEI Control reason (used by ACI), the value
+|                              has to be CL_IMEI_CONTROL_IMEI
+| Return      :           OK - 0
+|                      ERROR - negative values
++------------------------------------------------------------------------------
+*/
+extern BYTE cl_get_imeisv(USHORT imeiBufSize, UBYTE *imeiBufPtr, UBYTE imeiType)
+{
+#if CONFIG_MOKOFFS
+  USHORT ret;
+  UBYTE version;
+  UBYTE buf[SIZE_EF_IMEI];
+#else
+  BYTE ret;
+#endif
+
+  TRACE_FUNCTION("cl_get_imeisv()");
+
+  /*
+   * The user has required a stored IMEI. If it has been already read
+   * and stored, so return stored IMEI
+   */
+  if((imeiType == CL_IMEI_GET_STORED_IMEI) && (imei_flag == 1)){
+    memcpy(imeiBufPtr, stored_imei, CL_IMEI_SIZE);
+    return CL_IMEI_OK;
+  }
+  /*
+   * The user has required a "secure" IMEI. How we get it depends on what
+   * platform we are running on.
+   */
+
+#if CONFIG_MOKOFFS
+  /*
+   * Running on Openmoko GTA0x and using the original FFS.
+   * Get the nibble-swapped IMEI record from PCM.
+   */
+  ret = pcm_ReadFile ((UBYTE *)EF_IMEI_ID, SIZE_EF_IMEI, buf, &version);
+  if(ret == PCM_OK){
+    TRACE_EVENT("CL IMEI INFO: return IMEI-SV number from ffs:/pcm/IMEI");
+    /*
+     * swap digits
+     */
+    imeiBufPtr[0] = ((buf[0] & 0xf0) >> 4) | ((buf[0] & 0x0f) << 4);
+    imeiBufPtr[1] = ((buf[1] & 0xf0) >> 4) | ((buf[1] & 0x0f) << 4);
+    imeiBufPtr[2] = ((buf[2] & 0xf0) >> 4) | ((buf[2] & 0x0f) << 4);
+    imeiBufPtr[3] = ((buf[3] & 0xf0) >> 4) | ((buf[3] & 0x0f) << 4);
+    imeiBufPtr[4] = ((buf[4] & 0xf0) >> 4) | ((buf[4] & 0x0f) << 4);
+    imeiBufPtr[5] = ((buf[5] & 0xf0) >> 4) | ((buf[5] & 0x0f) << 4);
+    imeiBufPtr[6] = ((buf[6] & 0xf0) >> 4) | ((buf[6] & 0x0f) << 4);
+    imeiBufPtr[7] = ((buf[7] & 0xf0) >> 4) | ((buf[7] & 0x0f) << 4);
+    /* store IMEI */
+    memcpy(stored_imei, imeiBufPtr, CL_IMEI_SIZE);
+    imei_flag = 1;
+  }else{
+    /*
+     * pcm_ReadFile() can't really fail, as it merely reads out of a
+     * RAM buffer that was filled earlier, either from FFS or from
+     * compiled-in defaults.  But TI's original code had the following
+     * error handling clause, so I kept it.
+     */
+    TRACE_EVENT("CL IMEI INFO: return default IMEI-SV number");
+    memcpy(imeiBufPtr, C_DEFAULT_IMEISV_DSAMPLE, CL_IMEI_SIZE);
+  }
+  return CL_IMEI_OK;
+#else
+
+  /*
+   * Regular FreeCalypso configuration, not MokoFFS.
+   * We try to get the IMEISV from the following sources, in this order:
+   *
+   * /etc/IMEISV (sensible nibble order, not encrypted)
+   * Pirelli's encrypted IMEI record (Pirelli target only)
+   * hard-coded fallback and error indication
+   */
+
+  if (ffs_file_read(CL_IMEI_FFS_PATH, imeiBufPtr, CL_IMEI_SIZE) >= EFFS_OK) {
+    memcpy(stored_imei, imeiBufPtr, CL_IMEI_SIZE);
+    imei_flag = 1;
+    return CL_IMEI_OK;
+  }
+#if CONFIG_TARGET_PIRELLI
+  ret = pirelli_get_imeisv (imeiBufSize, imeiBufPtr);
+  if (ret == CL_IMEI_OK) {
+    imei_flag = 1;
+    return ret;
+  }
+#else
+  ret = CL_IMEI_READ_IMEI_FAILED;
+#endif
+  TRACE_ERROR("CL IMEI FATAL ERROR: IMEI not available!");
+  memcpy(imeiBufPtr, C_DEFAULT_IMEISV_DSAMPLE, CL_IMEI_SIZE);
+  return ret;
+#endif	/* CONFIG_MOKOFFS */
+}
+
+#endif /* CL_IMEI_C */