| /****************************************************************************** |
| *(C) Copyright 2008 Marvell International Ltd. |
| * All Rights Reserved |
| ******************************************************************************/ |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/stat.h> |
| #include <sys/un.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <termios.h> |
| #include <ctype.h> |
| #include <libgen.h> |
| #include <cutils/properties.h> |
| #include <errno.h> |
| #include "utilities.h" |
| #include "utlTrace.h" |
| #include "paths_defs.h" |
| |
| #define PROC_CMDLINE "/proc/cmdline" |
| #define CMDLINE_LEN 1024 |
| #define BSPFLG_NAME "PROD=" |
| #define ATMOD_FLAG "atcmdmode=" |
| |
| #define REGDUMP_FILE "/sys/power/regdump" |
| #define REG_LINE_LEN 1024 |
| #define CHIPID_ADDRESS "0xfe282c00" |
| #define REG_ADD_CON_SPLIT ':' |
| |
| #define EMMC_BOOT_FLAG "emmc_boot" |
| #define NEVO_TD_FLAG "nevo_td" |
| |
| #define HARDWARE_VERSION_FILE "/proc/cpuinfo" |
| #define HDVER_LINE_LEN 1024 |
| #define HDVER_KEY "Rev" |
| #define HDVER_KEY_VALUE_SPLIT ':' |
| |
| /* |
| * Defined here since strcasestr is not C99 standard. |
| * Find the first occurrence of find in s, ignore case. |
| */ |
| char *strcasestr(const char *s, const char *find) |
| { |
| char c, sc; |
| size_t len; |
| |
| if ((c = *find++) != 0) { |
| c = tolower((unsigned char)c); |
| len = strlen(find); |
| do { |
| do { |
| if ((sc = *s++) == 0) |
| return (NULL); |
| } while ((char)tolower((unsigned char)sc) != c); |
| } while (strncasecmp(s, find, len) != 0); |
| s--; |
| } |
| return ((char *)s); |
| } |
| |
| /* Defined here since (v)asprintf is not C99 standard */ |
| int vasprintf(char **ret, const char *format, va_list args) |
| { |
| int count; |
| va_list copy; |
| va_copy(copy, args); |
| |
| *ret = NULL; |
| |
| count = vsnprintf(NULL, 0, format, args); |
| if (count >= 0) |
| { |
| char* buffer = (char*) malloc(count + 1); |
| if (buffer != NULL) |
| { |
| count = vsnprintf(buffer, count + 1, format, copy); |
| if (count < 0) |
| free(buffer); |
| else |
| *ret = buffer; |
| } |
| else |
| count = -1; |
| } |
| |
| va_end(copy); |
| return count; |
| } |
| |
| int asprintf(char **ret, const char *format, ...) |
| { |
| int count; |
| va_list args; |
| |
| va_start(args, format); |
| count = vasprintf(ret, format, args); |
| va_end(args); |
| return count; |
| } |
| |
| int StringToInt(const char *pString, int *pVal, int strLen, int strMinLen, int strMaxLen, int valMin, int valMax) |
| { |
| int count; |
| int val; |
| |
| /* Check string length */ |
| if ((strLen < strMinLen) || (strLen > strMaxLen)) |
| return (-1); |
| |
| /* Check string characters, first character may be plus/minus sign */ |
| if ((!isdigit(pString[0])) && (pString[0] != '+') && (pString[0] != '-')) |
| return (-2); |
| for (count=1 ; count<strLen ; count++) { |
| if (!isdigit(pString[count])) |
| return (-2); |
| } |
| |
| /* Convert to integer */ |
| val = atoi(pString); |
| |
| /* Check integer value range */ |
| if ((val < valMin) || (val > valMax)) |
| return (-3); |
| |
| *pVal = val; |
| |
| return 0; |
| } |
| |
| int HexStringToInt(const char *pString, void *pVal, int strLen, int strMinLen, int strMaxLen, int sizeBytes) |
| { |
| int count; |
| unsigned long val; |
| |
| /* Check string length */ |
| if ((strLen < strMinLen) || (strLen > strMaxLen)) |
| return (-1); |
| |
| /* Check string characters */ |
| for (count=0 ; count<strLen ; count++) { |
| if (!isxdigit(pString[count])) |
| return (-2); |
| } |
| |
| /* Convert to integer */ |
| if (sizeBytes == 1) { |
| unsigned char *pChar = (unsigned char *)pVal; |
| for (count=0 ; count<((strLen+1)>>1) ; count++) |
| if (sscanf(&pString[count<<1], "%2lx", (unsigned long *)&val) == 1) |
| pChar[count] = (unsigned char)val; |
| else |
| return (-3); |
| } else if (sizeBytes == 2) { |
| unsigned short *pShort = (unsigned short *)pVal; |
| for (count=0 ; count<((strLen+3)>>2) ; count++) |
| if (sscanf(&pString[count<<2], "%4lx", (unsigned long *)&val) == 1) |
| pShort[count] = (unsigned short)val; |
| else |
| return (-3); |
| } else if (sizeBytes == 4) { |
| unsigned long *pLong = (unsigned long *)pVal; |
| for (count=0 ; count<((strLen+7)>>3) ; count++) |
| if (sscanf(&pString[count<<3], "%8lx", (unsigned long *)&val) == 1) |
| pLong[count] = (unsigned long)val; |
| else |
| return (-3); |
| } else { |
| return (-4); |
| } |
| |
| return 0; |
| } |
| |
| /* MRD still need to read /proc/cmdline after we drop root permission, |
| * so cache it in this function */ |
| int get_kernel_cmdline(char *buf, int len) |
| { |
| static char cmdline[CMDLINE_LEN]; |
| static int is_init = 0; |
| int ret = -1; |
| int fd; |
| |
| if(!buf || len <= 0) return -1; |
| |
| if(is_init) |
| goto INITED; |
| |
| fd = open(PROC_CMDLINE, O_RDONLY); |
| if (fd < 0) |
| goto ERR_RET; |
| |
| ret = read(fd, cmdline, CMDLINE_LEN); |
| close(fd); |
| |
| if(ret <= 0 || ret > CMDLINE_LEN) |
| goto ERR_RET; |
| cmdline[ret - 1] = '\0'; |
| |
| INITED: |
| ret = strlen(cmdline) + 1; |
| if(ret > len) |
| ret = len; |
| |
| strncpy(buf, cmdline, ret); |
| buf[ret - 1] = '\0'; |
| |
| is_init = 1; |
| |
| return ret; |
| |
| ERR_RET: |
| return -1; |
| } |
| |
| int get_bspflag_from_kernel_cmdline(void) |
| { |
| char cmdline[CMDLINE_LEN]; |
| char *pstr; |
| int ret; |
| static int is_init = 0; |
| static int flag = 0; |
| |
| if(is_init) return flag; |
| |
| ret = get_kernel_cmdline(cmdline, CMDLINE_LEN); |
| |
| if (ret < 0) |
| { |
| /* read error, goto err_ret */ |
| goto ERR_RET; |
| } |
| |
| ret = 0; |
| /* find the string "PROD=" in cmdline*/ |
| pstr = strstr(cmdline, BSPFLG_NAME); |
| if(pstr) |
| { |
| pstr += strlen(BSPFLG_NAME); |
| ret = atoi(pstr); |
| } |
| else // not found PROD, need to check atcmdmode flag |
| { |
| if (strstr(cmdline, ATMOD_FLAG)) |
| { |
| ret = DIAG_ATCMD_BSPFLAG; |
| } |
| } |
| |
| flag = ret; |
| is_init = 1; |
| |
| ERR_RET: |
| return ret; |
| } |
| |
| int InUARTProduction_Mode() |
| { |
| int bspflag; |
| |
| bspflag = get_bspflag_from_kernel_cmdline(); |
| if(bspflag == DIAG_UART_BSPFLAG || bspflag == DIAG_ATCMD_BSPFLAG) |
| return 1; |
| else |
| return 0; |
| } |
| |
| int InProduction_Mode(void) |
| { |
| int bspflag; |
| int ProdFlag = 0; |
| int is_prod = 0; |
| |
| ProdFlag = !access(PROD_FLAG_FILE, F_OK); |
| if (ProdFlag) |
| { |
| is_prod = 2; //production mode |
| } |
| else |
| { |
| bspflag = get_bspflag_from_kernel_cmdline(); |
| if((bspflag == DIAG_USB_BSPFLAG) || (bspflag == DIAG_UART_BSPFLAG)) |
| { |
| is_prod = 2; //production mode |
| } |
| else if(bspflag == DIAG_ATCMD_BSPFLAG) |
| { |
| is_prod = 1; //at cmd mode |
| } |
| } |
| |
| return is_prod; |
| } |
| |
| /* function: get_chipid() |
| * get chipid from regdump file. |
| * return value: <0 error; 1 success |
| */ |
| int get_chipid(unsigned long *chipid) |
| { |
| int ret = -1, len; |
| FILE *fp_reg = NULL; |
| char *pstr; |
| char regline[REG_LINE_LEN]; |
| |
| fp_reg = fopen(REGDUMP_FILE, "rb"); |
| |
| if (NULL == fp_reg) |
| { |
| ret = -2; |
| goto CH_ERR_RET; |
| } |
| |
| len = strlen(CHIPID_ADDRESS); |
| |
| while(NULL != fgets(regline, REG_LINE_LEN, fp_reg)) |
| { |
| if (!strncmp(regline, CHIPID_ADDRESS, len)) |
| { |
| pstr = strchr(regline, REG_ADD_CON_SPLIT); |
| // pstr+1: skip ':' |
| *chipid = strtoul(pstr+1, 0, 16); |
| ret = 1; |
| break; |
| } |
| } |
| fclose(fp_reg); |
| CH_ERR_RET: |
| return ret; |
| } |
| |
| /* function: get_hardwareVersion() |
| * get hardware version from /proc/cpuinfo. |
| * return value: <0 error; 1 success |
| */ |
| int get_hardwareVersion(char *hardwareVerBuf, int maxHdVerBufSize) |
| { |
| int ret = -1, hdVerKeyLen, hdVerValueLen; |
| FILE *fp = NULL; |
| char *pstr; |
| char line[HDVER_LINE_LEN]; |
| |
| fp = fopen("/proc/cpuinfo", "rb"); |
| |
| if (NULL == fp) |
| { |
| ret = -2; |
| goto ERR_RET; |
| } |
| |
| hdVerKeyLen = strlen(HDVER_KEY); |
| |
| while(NULL != fgets(line, HDVER_LINE_LEN, fp)) |
| { |
| if (!strncmp(line, HDVER_KEY, hdVerKeyLen)) |
| { |
| pstr = strchr(line, HDVER_KEY_VALUE_SPLIT); |
| if(pstr == NULL) |
| { |
| ret = -3; |
| break; |
| } |
| // ++pstr: skip ':' |
| hdVerValueLen = strlen(++pstr); |
| while(isspace(pstr[hdVerValueLen - 1])) |
| { |
| hdVerValueLen--; |
| } |
| pstr[hdVerValueLen] = '\0'; |
| // 1 is for the space between hdVerKey and hdVerValue |
| while(isspace(*pstr) || ((hdVerKeyLen + hdVerValueLen + 1 >= maxHdVerBufSize) && (*pstr == '0'))) |
| { |
| hdVerValueLen--; |
| pstr++; |
| } |
| if(hdVerKeyLen + hdVerValueLen + 1 >= maxHdVerBufSize || hdVerValueLen <= 0) |
| { |
| ret = -4; |
| break; |
| } |
| snprintf(hardwareVerBuf, maxHdVerBufSize, "%s %s", HDVER_KEY, pstr); |
| ret = 1; |
| break; |
| } |
| } |
| fclose(fp); |
| ERR_RET: |
| return ret; |
| } |
| |
| /* function: Is_TD_mode() |
| * judge whether the baseband is TD or UMTS |
| * return value: 1 TD; 0 UMTS |
| */ |
| BOOL Is_TD_mode() |
| { |
| #ifdef BIONIC |
| char baseband[PROPERTY_VALUE_MAX]; |
| property_get(SYS_BASEBAND_PROPERTY, baseband, ""); |
| if(strcmp(baseband, BASEBAND_TD) == 0) |
| return TRUE; |
| else if(strcmp(baseband, BASEBAND_UMTS) == 0) |
| return FALSE; |
| else |
| { |
| return FALSE; |
| } |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| int saveProcessName(const char *execPath, char *dest, unsigned int size) |
| { |
| int len; |
| char *pPath, *pBase; |
| if(execPath == NULL || dest == NULL) |
| return -1; |
| len = strlen(execPath); |
| pPath = (char *)malloc(len + 1); |
| if(pPath == NULL) |
| return -1; |
| strcpy(pPath, execPath); |
| pBase = basename(pPath); |
| if((len = strlen(pBase) >= size)) |
| { |
| free(pPath); |
| return -1; |
| } |
| strcpy(dest, pBase); |
| free(pPath); |
| return 0; |
| } |
| |
| BOOL isDualSimSolution() |
| { |
| #ifdef OPT_DSDS |
| return TRUE; |
| #else |
| |
| #ifdef BIONIC |
| char value[PROPERTY_VALUE_MAX]; |
| property_get("persist.radio.multisim.config", value, ""); |
| return !(strncmp(value, DS_KEY, strlen(DS_KEY))); |
| #else |
| return FALSE; |
| #endif |
| |
| #endif |
| } |
| |
| BOOL isSim2Master() |
| { |
| BOOL bDualSim = isDualSimSolution(); |
| if(bDualSim) |
| { |
| #ifdef OPT_DSDS |
| int ret; |
| char value[PROPERTY_VALUE_MAX]; |
| property_get("persist.sys.sim2.master.enable", value, "0"); |
| ret = atoi(value); |
| return ret != 0; |
| #else |
| return FALSE; |
| #endif |
| } |
| return FALSE; |
| } |
| |
| void setSim2Master(BOOL option) |
| { |
| #ifdef OPT_DSDS |
| if(option) |
| { |
| property_set("persist.sys.sim2.master.enable", "1"); |
| } |
| else |
| { |
| property_set("persist.sys.sim2.master.enable", "0"); |
| } |
| #else |
| (void) option; |
| #endif |
| return; |
| } |
| |
| int setDualSimType(int type) |
| { |
| int ret = 0; |
| BOOL bDualSim = isDualSimSolution(); |
| char value[PROPERTY_VALUE_MAX]; |
| |
| if(bDualSim) |
| { |
| snprintf(value, sizeof(value), "%d", type); |
| ret = property_set("persist.radio.multisim.type", value); |
| } |
| |
| return ret; |
| } |
| |
| /* 0: DUAL_SIM_DUAL_STANDBY |
| * 1: DUAL_SIM_SINGLE_STANDBY |
| * 2: DUAL_SIM_SGIT |
| * 3: DUAL_SIM_DUAL_STANDBY_FP |
| */ |
| int getDualSimType(void) |
| { |
| int type = -1; |
| BOOL bDualSim = isDualSimSolution(); |
| char value[PROPERTY_VALUE_MAX]; |
| |
| if(bDualSim) |
| { |
| property_get("persist.radio.multisim.type", value, "3"); |
| type = atoi(value); |
| } |
| |
| return type; |
| } |
| |
| void initDualSimType(int type) |
| { |
| BOOL bDualSim = isDualSimSolution(); |
| char value[PROPERTY_VALUE_MAX]; |
| int ivalue = -1; |
| |
| if(bDualSim) |
| { |
| property_get("persist.radio.multisim.type", value, "-1"); |
| ivalue = atoi(value); |
| |
| if (ivalue == -1) |
| setDualSimType(type); |
| } |
| } |
| |
| int openTtyDevice(const char* deviceName) |
| { |
| struct termios tio; |
| int serialfd1 = open(deviceName, O_RDWR); |
| |
| if (serialfd1 < 0) { |
| fprintf(stderr, "Error opening device %s: %s\n", deviceName, strerror(errno)); |
| goto exit; |
| } |
| (void)fcntl(serialfd1, F_SETFL, 0); |
| |
| memset(&tio, 0x0, sizeof(tio)); |
| tio.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD; |
| tio.c_iflag = IGNPAR; |
| |
| tio.c_cc[VERASE] = 0x8; /* del */ |
| tio.c_cc[VEOF] = 4; /* Ctrl-d */ |
| tio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */ |
| tio.c_cc[VEOL] = 0xD; /* '\0' */ |
| |
| tcflush(serialfd1, TCIFLUSH); |
| tcsetattr(serialfd1, TCSANOW, &tio); |
| exit: |
| return serialfd1; |
| } |
| |
| int connectUnixSocket(const char* socketName) |
| { |
| struct sockaddr_un addr; |
| int sock = socket(AF_UNIX, SOCK_STREAM, 0); |
| |
| if (sock < 0) |
| return -1; |
| |
| memset(&addr, 0, sizeof(addr)); |
| addr.sun_family = AF_UNIX; |
| strncpy(addr.sun_path, socketName, sizeof(addr.sun_path)-1); |
| if (/*TEMP_FAILURE_RETRY*/(connect(sock,(const struct sockaddr*) &addr, sizeof(addr))) /*!=*/ < 0) { |
| fprintf(stderr, "Error connect to socket %s: %s\n", socketName, strerror(errno)); |
| close(sock); |
| return -1; |
| } |
| return sock; |
| } |
| |
| BOOL eeh_sd_card_available(int rw) |
| { |
| #ifdef BIONIC |
| #define CHECK_SD_DIR "/lost+found" /*always exists */ |
| #else |
| #define CHECK_SD_DIR "/" /* unavaliable if not mounted */ |
| #endif |
| int ret, mode; |
| |
| mode = F_OK; |
| //if (rw) |
| mode |= R_OK | W_OK; |
| |
| ret = access(SDCARD_MOUNT CHECK_SD_DIR, mode); |
| return (ret == 0); |
| } |
| |
| |
| BOOL check_if_old_eeh_process(char *ind, BOOL is_cp_eeh_old_ver) |
| { |
| BOOL is_sd_dump = eeh_sd_card_available(0); |
| |
| if (is_sd_dump) |
| return TRUE; |
| |
| if (!is_cp_eeh_old_ver) { |
| return FALSE; |
| } else { |
| if (ind == NULL) |
| return FALSE; |
| |
| if (!strcmp(ind, "old_ap_eeh")) |
| return TRUE; |
| |
| if (!strcmp(ind, "new_ap_eeh")) |
| return FALSE; |
| |
| #ifdef CONFIG_ASR1901_EEH |
| if (!strcmp(ind, "com_DTCM.bin") || |
| !strcmp(ind, "com_ITCM.bin") || |
| !strcmp(ind, "com_GBDump.bin") || |
| !strcmp(ind, "com_IPCDump.bin") || |
| !strcmp(ind, "com_L2_bx2.bin") || |
| !strcmp(ind, "com_L1_bx2c.bin") || |
| !strcmp(ind, "com_BSRAM.bin") || |
| !strcmp(ind, "com_RAMLOG.bin") || |
| !strcmp(ind, "com_bx2du0.bin") || |
| !strcmp(ind, "com_bx2du1.bin")) |
| return TRUE; |
| else |
| return FALSE; |
| #elif CONFIG_ASR1903_EEH |
| if (!strcmp(ind, "com_DTCM.bin") || |
| !strcmp(ind, "com_ITCM.bin") || |
| !strcmp(ind, "com_L1_bx2c.bin") || |
| !strcmp(ind, "com_L2_bx2.bin") || |
| !strcmp(ind, "com_squ.bin") || |
| !strcmp(ind, "com_RAMLOG.bin")) |
| return TRUE; |
| else |
| return FALSE; |
| #else |
| if(!strcmp(ind, "com_DTCM.bin") || |
| !strcmp(ind, "com_ITCM.bin") || |
| !strcmp(ind, "com_GBDump.bin") || |
| !strcmp(ind, "com_IPCDump.bin")) |
| return TRUE; |
| else |
| return FALSE; |
| #endif |
| } |
| } |
| |
| ssize_t readFile(const char* path, void* buf, size_t len) |
| { |
| int fd = open(path, O_RDONLY); |
| if (fd < 0) |
| return TEL_FILE_OPEN_FAILED; |
| ssize_t size = read(fd, buf, len); |
| close(fd); |
| if (size < 0) |
| return TEL_FILE_READ_FAILED; |
| return size; |
| } |
| |
| #ifdef __GLIBC__ |
| |
| size_t strlcat(char *dst, const char *src, size_t size) |
| { |
| size_t srclen; /* Length of source string */ |
| size_t dstlen; /* Length of destination string */ |
| |
| dstlen = strlen(dst); |
| size -= dstlen + 1; |
| |
| if (!size) |
| return (dstlen); /* No room, return immediately... */ |
| |
| srclen = strlen(src); |
| |
| if (srclen > size) |
| srclen = size; |
| |
| memcpy(dst + dstlen, src, srclen); |
| dst[dstlen + srclen] = '\0'; |
| |
| return (dstlen + srclen); |
| } |
| #endif |
| |